GoogleChrome / lighthouse-ci

Automate running Lighthouse for every commit, viewing the changes, and preventing regressions
Apache License 2.0
6.33k stars 632 forks source link

Documentation: How to test a site in dark mode #1022

Open ptmkenny opened 3 months ago

ptmkenny commented 3 months ago

Is your feature request related to a problem? Please describe.

The accessibility assessment checks contrast ratios. Websites often provide a light theme and a dark theme, and it is common to for the site to automatically set the theme based on the browser/OS preference.

Describe the solution you'd like

It would be great to have an easy way to run "dark mode" tests against sites that let the browser/OS select the theme.

Describe alternatives you've considered

I read through the documentation but it seems quite complicated to set up, and searching for "dark mode" yielded no results.

Elte156 commented 3 months ago

it is common to for the site to automatically set the theme based on the browser/OS preference

@ptmkenny can you provide an example site that does this? I'm curious what triggers are available for a site to automatically adjust to dark mode.

ptmkenny commented 3 months ago

@Elte156 Sure, https://bulma.io/.

You will see whatever your browser/OS preference is, but you can change it by opening a new tab in Chrome, go to settings -> appearance -> light/dark and refreshing the page.

Looking into this myself, I found Puppeteer has Page.emulateMediaFeatures():

await page.emulateMediaFeatures([
  {name: 'prefers-color-scheme', value: 'dark'},
]);

But I don't know a convenient way to make use of this with lighthouse.

Elte156 commented 3 months ago

Thank you. @ptmkenny These are the triggers I was looking for:

When I visit bulma.io, the light/dark mode tests didn't work for me (maybe because this color scheme detection is experimental at the moment).

What I did notice were these request headers (didn't include header Sec-CH-Prefers-Color-Scheme: "dark"): image

So perhaps try this in your lighthouse config and see if it does what you expect:

{
  "ci": {
    "collect": {
      "settings": {
        "extraHeaders": "{\"Sec-CH-Prefers-Color-Scheme\": \"dark\"}"
      }
    }
  }
}
ptmkenny commented 3 months ago

Thanks for this information.

I tried your suggested config but it doesn't seem to work:

lhci  --config .dark.json collect --url https://www.bulma.io

In this case, on my local machine (macOS, OS set to dark mode), for the three test runs:

If I change the config to be light instead of dark, the result is the same (dark, then light and light again).

If I run without the config, then the result is the same (dark - light - light).

On GHA, I always seem to get light mode, even with the config.

Elte156 commented 2 months ago

Then it seems that bulma.io doesn't respond to that special CH header.

When you run it locally on your Mac, what does the UserAgent request header read when you load bulma.io? I suspect that's the other way how the OS/browser tells the website which theme mode to load.

ptmkenny commented 2 months ago

@Elte156 It must be something that the OS/Chrome is doing itself because, in addition to changing from Light to Dark and back in the browser, I noticed I can also change between Light and Dark in macOS, and the Bulma website (and my personal website, which is based on Bulma) both automatically switch between light and dark mode.

I checked the headers when in light mode and in dark mode and they don't change; they are exactly the same, but dark or light mode is returned depending on the browser or OS preference.

Bulma is a CSS-only framework, so this is not due to JS.

So the question is how to put lighthouse's browser/OS into "dark mode"?

ptmkenny commented 2 months ago

It seems Chrome has a flag for forcing dark mode:

--enable-features=WebContentsForceDark

Is there a way to use this flag with lighthouse-ci?

Elte156 commented 2 months ago

I was able to see this work when I change my macOS appearance from light to dark and it's instantaneous (no page reload needed). Pretty cool.

There is a way to feed the chrome instance options. Take a look here at all the flags available: https://bit.ly/chrome-flags

Try this and see if it works:

{
  "ci": {
    "collect": {
      "settings": {
        "chromeFlags": "--force-dark-mode"
      }
    }
  }
}
ptmkenny commented 2 months ago

@Elte156 Unfortunately, that did not work. It seems there is something special about the dark mode behavior, but I can't find good documentation for it so I asked Stack Overflow. I'll update when I find a reliable way to do this.

ptmkenny commented 2 months ago

Ok, I think the issue is this.

The way to force Chrome to enable dark mode is to use --enable-features=WebContentsForceDark. So, for example, I can launch Chrome and see my site in dark mode with this command on macOS.

open -a Google\ Chrome --args --enable-features=WebContentsForceDark

However, when I access chrome://version/ and check the Command Line parameters, this is the result:

/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --enable-features=WebContentsForceDark --flag-switches-begin --flag-switches-end

So --enable-features=WebContentsForceDark is not a "flag" in the sense that it goes between --flag-switches-begin and --flag-switches-end. Maybe this is why it's failing when I use chromeFlags?

hamirmahal commented 6 days ago

I was just about to create an issue for this.

Do you have your CI setup to run Lighthouse once with your web-app's default theme, and then again with a night theme active? I'm curious to see how the configuration files for that would look.