Illustration of theme/scheme disconnect in squidfunk/mkdocs-material#2727
Setup
Consider this …
1 2 3 4 |
|
… which renders as:
Expected behavior
From the docs:
In order to automatically set the color palette to the user's system preference, a media query can be set as part of the
media
field next to the toggle definition inmkdocs.yml
:
1 2 3 4 5 6 7 8 9 10 11 12theme: palette: - media: "(prefers-color-scheme: light)" scheme: default toggle: icon: material/toggle-switch-off-outline name: Switch to dark mode - media: "(prefers-color-scheme: dark)" scheme: slate toggle: icon: material/toggle-switch name: Switch to light mode
When the user first visits your site, the media queries are evaluated in the order of their definition. The first media query that matches selects the default color palette.
After reading the above, as well as squidfunk/mkdocs-material#1266, my understanding is:
- Toggling the theme using the toggle switch will switch the preferred color scheme; and
- Switching the preferred color scheme will toggle the theme.
However, they are disconnected as far as I can tell.
Observed behavior
- Toggling the theme using the switch in the header of this page will update the theme, but not the scheme.
- Toggling the preferred color scheme (e.g., on MacOS, switching from
Light
toDark
inSystem Preferences
»General
»Appearance
) will update the scheme, but not the theme.
Detail
Test matrix:
Theme 👉 Scheme 👇 |
Light | Dark |
---|---|---|
Light | ||
Dark |
Tested with:
package | version |
---|---|
mkdocs | 1.1.2 |
mkdocs-material | 7.1.6 |
mkdocs-material-extensions | 1.0.1 |
Work-around using extra_css
to tie image selection to user-selected theme
Consider this …
1 2 3 4 5 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 |
|
… which renders as:
This leverages the custom color scheme overrides mechanism to tie image presentation to the chosen theme, which gets close to the desired behavior.
Pros
- It preserves the existing theme toggle behavior.
- It’s a pretty minimal intrusion (four lines of CSS and use of the
extra_css
setting). - It’s pretty readable.
If you were ignorant (or forgetful) of the approach, and came across one of the
<img …>
s, you probably wouldn’t have to do too much digging to find out what was going on.
Cons
- It’s bespoke.
- It’s pretty fragile. The CSS selectors are tied to the theme names. One could probably work around this as well, but they probably add a disproportionate amount of complexity for their value.
- All image variants are retrieved on page load, even those that won’t be displayed until a theme change (which is probably a rare event). This isn’t ideal, and gets worse as the number of theme-specific image variants increases.
Work-around using extra_javascript
to tie theme selection to prefers-color-scheme
Consider this …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
… and let’s revisit this (from above) …
1 2 3 4 |
|
… which would render¹ as:
Note
¹ This is emulated here using image_theme_emulated.js
in lieu of image_theme.js
.
This is to preserve the aforementioned disconnected behavior for observation/experimentation.
This adapts this approach to tie theme selection to the chosen prefers-color-scheme
, which emulates the desired behavior.
Pros
- It’s a pretty minimal intrusion (some straightforward JavaScript, and use of the
extra_javascript
setting). - It works with existing standard approaches like the `
Cons
- It fights with the user selected theme toggle.
Consider disabling it by deleting any
theme
»palette
»toggle
settings. - It’s still pretty fragile. The JavaScript is tied to the theme names.