Sometimes it is convenient to use a web view to show some static HTML content in an iOS app. If you have adopted dynamic type elsewhere in your app it can look odd if that text does not also respect the user’s choice of content size. Luckily there is a way to use dynamic type when displaying text in a web view.
Last updated: Jun 12, 2020
Using Apple System Fonts
It turns out to be easy to use dynamic type with HTML content. You just need to choose the Apple system fonts when specifying the CSS font
property. As long as you are on an Apple device you can use these fonts:
font: -apple-system-body
font: -apple-system-headline
font: -apple-system-subheadline
font: -apple-system-caption1
font: -apple-system-caption2
font: -apple-system-footnote
font: -apple-system-short-body
font: -apple-system-short-headline
font: -apple-system-short-subheadline
font: -apple-system-short-caption1
font: -apple-system-short-footnote
font: -apple-system-tall-body
For example, to have the HTML body default to the Apple system font body style:
body {
font: -apple-system-body;
}
Note: If you are using the same content for non-Apple devices you should include a fallback font.
Example Using a WebKit View
A quick example to show how this works with a WKWebView
. Here is a simple HTML document that I want to show in my iOS app:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<link rel="stylesheet" href="stylesheet.css">
<title>User Guide</title>
</head>
<body>
<h1>Dynamic Type With WebKit</h1>
<h2>Getting Started</h2>
<p>An example of using <mark>dynamic type</mark> fonts with HTML content displayed in a WKWebView. Changing the text size in Settings should also change the text in this web view.</p>
<footer>For more details see <a href="https://useyourloaf.com/blog/using-dynamic-type-with-web-views/">Using Dynamic Type With Web Views</a></footer>
</body>
</html>
This references a CSS stylesheet (stylesheet.css
) that I include in the application bundle along with the HTML file to style the body, headings and footer:
body {
font: -apple-system-body;
}
h1 {
font: -apple-system-headline;
color: red;
}
h2 {
font: -apple-system-subheadline;
color: green;
}
footer {
font: -apple-system-footnote;
}
Using A WKWebView
To show the HTML I’m created a view controller with a WKWebView
. I have disabled JavaScript but otherwise I’m using a default configuration when creating the WKWebView
.
import UIKit
import WebKit
final class WebViewControler: UIViewController {
private lazy var webView: WKWebView = {
let preferences = WKPreferences()
preferences.javaScriptEnabled = false
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
return WKWebView(frame: .zero, configuration: configuration)
}()
I load the HTML from the main bundle, using “default.html” as the default:
var html: String = "default" {
didSet {
loadHTML(html)
}
}
private func loadHTML(_ name: String) {
if let url = Bundle.main.url(forResource: name, withExtension: "html") {
webView.loadFileURL(url, allowingReadAccessTo: url)
}
}
To keep it simple I make the web view the root view of the view controller in loadView
:
override func loadView() {
view = webView
loadHTML(html)
}
Responding To Changes
Unfortunately there is no adjustsFontForContentSizeCategory
property on WKWebView
to automatically update fonts when the content size changes. Instead we need to listen for the notification and reload the view. Add the following line to loadView
or viewDidLoad
to observe the UIContentSizeCategory
notification:
NotificationCenter.default.addObserver(self,
selector: #selector(contentSizeDidChange(_:)),
name: UIContentSizeCategory.didChangeNotification,
object: nil)
The target method reloads the web view:
@objc private func contentSizeDidChange(_ notification: Notification) {
webView.reload()
}
Here is how the view looks on an iPhone 8 at the default content size:
Here is how it looks after changing the content size to the largest accessibility size:
Supporting Dark Mode
I’ve also updated the project to support dark mode. This requires iOS 13. See the following post for details:
Get The Code
You can get the full Xcode project for this post from my GitHub repository: