WKWebView Dark and Light Mode with dynamic URL in Swift 5
Asked Answered
N

3

4

I created WKWebView that doesn't have one url. User use this WKWebView as Safari means user can search anything on WKWebView. I am facing one issue when I change dark and light mode my web view will show me only white(Light) mode. My app is working on both mode all things working fine except WKWebView.

Already search on SO not find any related question on this. how to use iOS 13 darkmode for wkwebview

I refer this blog but it's static url so it will not help me out

https://useyourloaf.com/blog/using-dynamic-type-with-web-views/

Also checked opaque and background property but not working for me!

IMPORTANT User can search anything like google.com, photos or any surfing etc.

class DownloadViewController: UIViewController {
    
    @IBOutlet weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.uiDelegate = self
        webView.navigationDelegate = self
        webView.load(URLRequest(url: URL(string: "https://www.google.com")!))
        webView.allowsBackForwardNavigationGestures = true
        webView.allowsLinkPreview = true
    }

}

First I am loading Google site then depend on user(Totally dynamic not one url here).

Please suggest me! Thank you.

Nubbin answered 3/11, 2021 at 19:14 Comment(0)
U
4

You can use injecting CSS technic to add Light/Dark feature to your loaded web pages e.g:

// Load a web page
webView?.load(URLRequest(url: URL(string: "https://google.com")!))

// Inject Light/Dark CSS

let lightDarkCSS = ":root { color-scheme: light dark; }"
let base64 = lightDarkCSS.data(using: .utf8)!.base64EncodedString()

let script = """
    javascript:(function() {
        var parent = document.getElementsByTagName('head').item(0);
        var style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = window.atob('\(base64)');
        parent.appendChild(style);
    })()
"""

let cssScript = WKUserScript(source: script, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
webView?.configuration.userContentController.addUserScript(cssScript)

Result:

WKWebView: Google dark mode

To support page changing you can move insertion code to didCommitNavigation notification:

func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
    ...
    // Inject CSS here
}

NOTE: It doesn't work with any web page in general because some of web sites can hardcode colors of background, fonts etc. but you can tune specific pages as well by overriding its CSS.

Undeviating answered 8/11, 2021 at 10:16 Comment(4)
It's only working with google. so which approach would be correct if I want to do for any web page Inject or interfaceStyle?Nubbin
@YogeshPatel it can work with web pages that doesn't have hardcoded colors for backgrounds etc. but you can inject CSS dynamically and override known styles for certain web sites only so there is no a general solution as I mention above.Undeviating
okay understood!Nubbin
Why is the base64 encoding/decoding required? I see that it doesn't work without it, but it doesn't make sense to me.Aldenalder
I
0

Already search on SO not find any related question on this.

Interesting that you mention this, as this has been a question addressed quite a few times already. A quick search will show many good answers and threads, for example: this one.

That being said, the quick answer is:

WKWebView can adopt light and dark mode, like any other UIView/NSView. You can manually set the interfaceStyle on the appearance, or it will inherit it. More details here overrideUserInterfaceStyle.

But

Probably the problem you are facing is that even though the WKWebView is using the dark interfaceStyle, websites still show on light mode. That is because those websites (google and any other website/URL) are independent and handle their style on their own. Some of them adjust to match your device's interface style, but not all. In short, even if WKWebView is on dark mode, Google will load a white background if they want to do it.

As mentioned by others, you can change this behaviour by manually injecting CSS, please check those answers if that is what you want to do, check also the link I posted at the beginning of this answer where they discuss that approach.

Inositol answered 8/11, 2021 at 10:35 Comment(3)
I checked but its not working #57204409Nubbin
@YogeshPatel you need to manually inject CSS, probably via JavaScript. Every website is different so it might work for some but not others, it is not really straightforward and there can be many different approaches. Difficult to tell what exactly is not working for you, please post your Swift code, your JavaScript code, your CSS code, and the website that you are trying to modify with that code. With the code posted so far you have not even started to try to inject anything.Inositol
I tried many css code but it's not working so haven't mentioned that code because it's not working google site to @iuril code is only work for google. so Which approach would be correct if I want to do for any web page Inject or interfaceStyle?Nubbin
S
0

As in android web views(force_darkmode), Apple has not provided support for dark mode web-views yet. you can explore safari with a few reputed websites, even though they don't convert to dark mode. so we should wait for Webkit dark mode support till then. These CSS injections are not the best practice or robust solution.

Shopkeeper answered 11/11, 2021 at 13:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.