Search code examples
swiftuiwkwebview

Dynamic type in WKWebview not matching settings


I'm working on a SwiftUI iOS app, and I have a WKWebView that loads a local HTML file and CSS. I'm using the -apple-system fonts with iu-rounded and ui-sans-serif families, but when I go to settings and change the font size to larger in settings, the fonts on the page stay the same (dynamic type doesn't adjust), even after restarting the app, the fonts are always the same (the rest of the app's fonts changes as expected).

The font families do get applied, but the sizing doesn't.

How I'm adding the WKWebview to SwiftUI:

import SwiftUI
import WebKit

struct WebView : UIViewRepresentable {
    
    
    func makeUIView(context: Context) -> WKWebView  {
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context) {
        if let url = Bundle.main.url(forResource: "help", withExtension: "html") {
            uiView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
        }
    }
}


struct HelpView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    var body: some View {

    //some other stuff here (a title and a dismiss button)
               
         WebView()

    }
}

The HTML:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Help</title>

    <link rel="stylesheet" href="style.css">

</head>
<body>
<!-- A bunch of HTML here-->
<h2>Some headings</h2>
<p>And some text in paragraphs and lists</p>
</body>
</html>

The CSS:

:root {
    color-scheme: light dark;}
    --background:#ffffff;
    --text: #212121;
    --accent: #6C10EA;
}

html {
    font:-apple-system-body;
}

body {
    background-color: var(--background);
    line-height: 1.4;
    font-family: ui-sans-serif;
}

h2 {
    font:-apple-system-largetitle;
    font-family:ui-rounded;
}

img {
    max-width: 100%;
}

@media screen and (prefers-color-scheme: dark) {
  :root {
      --background:#171619;
      --text: #F3EBFF;
      --accent: #9140FF;
  }
}



Solution

  • In case anyone has the same issue, I was able to mimic it by passing the current body text size to the HTML, and setting that as the default. Just make sure that your other fonts use a relative font size (em) so they increase size when you change the body font-size:

    The code to add the web view:

    import SwiftUI
    import WebKit
    
    struct WebView : UIViewRepresentable {
            
        func makeUIView(context: Context) -> WKWebView  {
            
            return WKWebView()
        }
        
        func updateUIView(_ uiView: WKWebView, context: Context) {
    
            let bodySize = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body).pointSize
    
            if let url = Bundle.main.url(forResource: "help", withExtension: "html"), let param = URL(string: "?size=\(bodySize)", relativeTo: url) {
                uiView.loadFileURL(param, allowingReadAccessTo: url.deletingLastPathComponent())
            }
        }
    }
    
    
    struct HelpView: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
        
        var body: some View {
               // Other content here
               WebView()
                
            }
        }
    }
    

    HTML:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <title>Help</title>
    
        <link rel="stylesheet" href="style.css">
    
    </head>
    <body>
    <h2>Some Headings</h2>
    <p>Some content</p>
    
    
    <script>
        const queryString = window.location.search;
        const urlParams = new URLSearchParams(queryString);
        const size = urlParams.get('size');
        document.body.style.fontSize = size + "px";
    </script>
    </body>
    </html>