WebView typography is not governed by web standards but by the underlying OS. iOS draws with San Francisco and PingFang SC, which support the full 100–900 weight range; Android draws with Roboto and Noto, where older builds expose only 400/500/700 and 500 is quietly downgraded to 400. Font fallback diverges — Noto Color Emoji on Android versus Apple Color Emoji on iOS — and vendor kernels such as Tencent X5 disable non-whitelisted font fallback entirely. System text zoom overrides CSS: Android WebSettings.setTextZoom and iOS UIContentSizeCategory silently multiply every px, rem, and em, breaking layouts. The result is brand typography that looks right on one engine and broken on the next — tofu emoji, collapsed weights, and layout overflow. A host-owned runtime locks typography: a controlled font stack, capped system zoom, guaranteed fallback fonts, and consistent weight mapping the page cannot drift from.
One font list, two different drawings
The same font-family declaration resolves to different glyphs, hinting, and weight maps on each platform. PingFang SC on iOS carries the full 100–900 range, while Android's system Roboto — especially on older builds — ships only 400, 500, and 700, and 500 is often ignored or downgraded to 400. A font-weight: 500 that looks like a clean medium on iOS renders as plain 400 on Android, or as an outline-stroked fallback that looks heavier than intended. Listing -apple-system, Roboto, "PingFang SC" does not reconcile the two; the engine just picks the first name it can actually draw and ignores the rest.
Fallback breaks where it matters most
CJK and emoji are where fallback chains snap. Android WebView based on Chromium still ships Droid Sans Fallback by default on many devices, which does not cover Unicode extension regions — new emoji, rare CJK extension characters — so they render as tofu boxes or question marks. iOS fares better on recent Unicode but still falls back to an unsupported font if the page never declares UTF-8 or a fallback family. Vendor kernels make it worse: Tencent X5 can disable non-whitelisted font fallback outright, so even web fonts you load may not apply. The brand's carefully chosen typeface is only as good as whatever the device happens to have installed.
System zoom silently overrides your CSS
This is the quiet killer. On Android, the system settings inject a global scale factor that WebSettings.setTextZoom reflects, and the WebView multiplies px, rem, and em by it before layout. On iOS, UIContentSizeCategory pushes dynamic type into the page. The override is mandatory: a fixed-height container with enlarged text overflows and truncates, a precise Flex or Grid layout compresses as font sizes balloon, and responsive breakpoints break because the page is forced into desktop-style logic. The page never asked for it and cannot opt out through CSS alone.
The runtime fix
A host-owned runtime makes typography deterministic across engines. It injects a controlled font stack so every platform sees only the families it can actually draw, ships guaranteed fallback fonts — Noto Sans CJK plus Noto Color Emoji — so emoji and rare glyphs never become tofu, normalizes -webkit-font-smoothing for consistent antialiasing, and enforces a single weight map so 500 means 500 everywhere. It caps system text zoom at a safe value and preloads the brand fonts. The page renders the same because the runtime, not the device, decides the type.
| Dimension | WebView | Host-owned runtime |
|---|---|---|
| Weight mapping | iOS full 100–900; Android 400/500/700, 500 downgraded | Single enforced weight map |
| Font fallback | Divergent; X5 disables non-whitelist | Guaranteed Noto CJK + Color Emoji |
| Emoji / rare glyphs | Tofu boxes on many Android builds | Always drawn, never missing |
| System zoom | Mandatory override, breaks layout | Capped at safe value |
| Antialiasing | Inconsistent per engine | Normalized across platforms |
| Brand consistency | Per-device luck | Same render everywhere |
The series keeps returning to one fact: a WebView inherits the platform's weakest surfaces and adds a web-shaped one. Typography is the surface users see first and judge fastest — and in a stock WebView it is the one the device, not the designer, controls. A runtime puts the brand back in charge of its own type.
Sources
- PHP.cn — Mobile font rendering differences: iOS -apple-system vs Android Roboto glyph, hinting, and weight mapping differ; font-weight 500 ineffective on Android WebView; X5 disables non-whitelist fallback — the per-engine divergence in how weights and fallbacks resolve.
- TrueSight — Defensive WebView typography: Android textZoom and iOS UIContentSizeCategory force-override CSS; setTextZoom(100) to lock — how system zoom breaks layouts and the lock.
- CSDN Q&A — Emoji / rare CJK render as tofu in WebView; missing font fallback and HarfBuzz / Color Emoji on low Android versions — why glyphs disappear and how to inject Noto fonts.
- ByteDance — WebView rendering principles: WebKit (iOS) vs Blink (Android) pipeline differences, including font-smoothing inconsistency — the engine-level split behind rendering drift.
- Web.dev — Web on Android: WebView is part of the OS rendering pipeline and lacks the browser's consistency controls — the structural reason typography is device-dependent.