Skip to content

apple: fit_width_by_view leaves a paged document at actual size in WKWebView #761

Description

@andiwand

Taking 6.11.0 into OpenDocument.ios (opendocument-app/OpenDocument.ios#185), HtmlViewportMode::fit_width_by_view — the mode #726 asked for and #745 added for this app — makes text documents render worse than automatic does. Measured on an iPhone 17 Pro simulator, iOS 26, against the app's own ODT sample.

What the two modes emit

automatic:        <meta name="viewport" content="width=device-width,user-scalable=yes">        --odr-fit:auto
fit_width_by_view <meta name="viewport" content="width=device-width,initial-scale=1.0,...">    --odr-fit:view

Same config otherwise: text_document_margin=true, embed_shipped_resources=true, embed_images=false, relative_resource_paths=false, color_scheme=system.

What the reader sees

portrait after a rotation to landscape
automatic A4 page fitted to the width, whole page and its table visible refits
fit_width_by_view page at actual size, body text ~2× and reflowed to the screen; only the first third on screen same

Screenshot-diffing the two builds frame for frame, the ODT differs on 11.4% of pixels in portrait. Switching that one line off and changing nothing else takes it to 1.2%, so the mode is the cause and nothing else in the bump is.

The heading stays the same size while the body doubles, so this is not a zoom being applied at the wrong factor — it reads as no fit at all, with the layout at its natural measure.

Why it is worse than the mode it replaces

initial-scale=1.0 is doing exactly what #745 says it does: it stops the host fitting the page. The premise was that the view's own script then applies the fit instead. In WKWebView the pin lands and the compensating zoom does not, so the mode removes the fit the app had and puts nothing back.

automatic has no initial-scale, and WKWebView fits the page itself — which is the behaviour #726 records as absent on iOS. Whatever was true when #706 was filed, on iOS 26 the app renders correctly with automatic and no user script at all in portrait. It still needs its script on rotation: automatic alone does not refit after a width change (9% of pixels differ from the shipping build). So the split today is: WKWebView fits at load, nothing refits on rotation, and fit_width_by_view does neither.

Not established here

Why the view's script does not apply its factor — whether it does not run, runs and measures no overflow, or measures against a viewport WKWebView reports differently under a pinned scale. The app has embed_shipped_resources=true, so the js is in the page. Nothing was checked in Safari on macOS for comparison.

For now

The iOS PR keeps its user script and does not set the mode. Happy to run anything against a build here — the harness photographs each screen portrait, landscape and back, and diffs two builds frame for frame.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions