iOS の Dynamic Type を WKWebView 上でも正しくスケールさせる方法を示すデモアプリです。
ネイティブ SwiftUI コンポーネントは Dynamic Type に自動対応しますが、WebView 内の HTML/CSS はデフォルトでは追従しません。
このアプリでは、2 つのシンプルな実装ポイントを使って WebView 内のテキストを Dynamic Type に連動させる方法を示します。
NotificationCenter.default.addObserver(
self,
selector: #selector(dynamicTypeDidChange),
name: UIContentSizeCategory.didChangeNotification,
object: nil
)
@objc private func dynamicTypeDidChange() {
applyFontSize()
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
applyFontSize() // ページロード完了時にも適用
}
private func applyFontSize() {
let size = UIFont.preferredFont(forTextStyle: .body).pointSize
webView?.evaluateJavaScript(
"document.documentElement.style.fontSize = '\(size)px'",
completionHandler: nil
)
}UIContentSizeCategory.didChangeNotification を受信したら、Swift 側で body サイズを取得し evaluateJavaScript で :root の font-size を直接書き換えます。
リロードが不要なため即時反映され、注入する値を変えれば独自のスケール(上限キャップなど)にも対応できます。
:root {
font-size: 17px; /* フォールバック。Swift が evaluateJavaScript で上書きする */
}
.title { font-size: 1.143rem; } /* ✅ :root 基準でスケールする */
.description { font-size: 0.857rem; } /* ✅ :root 基準でスケールする */
.bad-title { font-size: 16px; } /* ❌ 固定値のためスケールしない */Swift が :root の font-size を書き換えるため、rem 指定の要素がすべて連動してスケールします。
- Xcode でプロジェクトを開いてシミュレーターまたは実機で起動
- 設定 → アクセシビリティ → 画面表示とテキストサイズ → さらに大きな文字 でフォントサイズを変更
- アプリに戻ると(リロードなしで)
rem指定のテキストのみサイズが変化することを確認できる
font: -apple-system-body を CSS に指定し、通知受信時に webView.reload() を呼ぶだけでも同様の効果が得られます。
実装はシンプルですが、リロードが発生する点と Apple のスケールに固定される点が evaluateJavaScript 方式との違いです。
/* CSS: -apple-system-body を指定するだけでよい */
:root, body { font: -apple-system-body; }// Swift: リロードで CSS を再評価させる
@objc private func dynamicTypeDidChange() {
webView?.reload()
}- iOS 16.0+
- Xcode 15+
- Swift 5.9+