Support dark mode toggle for SVGs and highlight.js#4925
Support dark mode toggle for SVGs and highlight.js#4925marcoscaceres merged 5 commits intospeced:mainfrom
Conversation
Syntax highlighting already works with automatic preferences, but has not played well with neither default (no dark mode) settings, nor worked with the manual scheme toggle. (See also speced#4871.) This fixes that using CSS (so that default behavior works without JS). SVG behavior is by default based on user-agent preferences, and has therefore also not played well with the manual toggle. With this change, that is now handled by setting `color-scheme: light` or `dark` on the body element, based on the sidebar-provided manual scheme toggle. If no meta element indicating dark color-scheme support is present, light mode is set on the body. This instructs SVGs to render in light mode when embedded in documents with no dark mode support, even when the user agent indicates dark mode. (The `color-scheme` CSS property can of course still be set to other values for various sections in a document, if so desired.) A darkmode example document is also added, containing syntax-highlighted code and embedding an SVG document supporting light/dark color-scheme preferences.
|
Is there anything I can to to help out with this? |
|
Sorry for the delay in review. I've some concerns:
I don't feel too comfortable with the approach here of Regardless, I'd suggest removing the Updated branch so the Netlify PR preview works. |
✅ Deploy Preview for respec-pr ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Thank you for the reply! (And sorry for my response delay.) I think this is important to resolve, as currently live specs without darkmode support enabled (or user-overridden with these controls) still displays highlighted code and colorscheme-aware SVGs in dark mode. This is not only a visual discrepancy, but IMHO an accessibility concern.
I understand and support that. It is currently (2025-06-14) at 92.8% support according to Can I Use though, which I believe should be compared to 95.16% for prefers-color-scheme support in general. And this gap will likely close over time? (I'm not properly acquainted with the QQ, Baidu nor KaiOS browsers; but I think they're still Chromium, Webkit and Gecko-based respectively; so the upstream support is already there.)
I share these concerns, and humbly ask for explicit guidance on how to proceed. The styling is spread out between the tr-design repo and respec, and respec "inherits" tr-design here with respect to the dark mode controls. Alas I'm also limited on time, and I cannot devote much energy into simplifying the layered stack set up here. What's your advice to reduce the brittleness? Since the controls are JS-based, anyone having JS turned off cannot override darkmode without changing it globally in their browser or OS. This PR aimed to reduce this JS-dependency somewhat, but perhaps adding an explicit "lightmode" via the JS in the tr-design is another way to go. I'm not convinced that would be less brittle though, as there is still a cross-repo dependency with no change control. Pinning versions of tr-design might be a way to at least controlling the risk of the CSS in the PR breaking if the markup from "upstream" changes. Or to move some of this PR to tr-design. But since the highlighting is something respec controls; I thought it practical enough to put this solution wholly in respec.
None of the existing examples are darkmode-enabled, which is why I made a dedicated example. Which of them would you suggest I update in this fashion?
Thank you. |
marcoscaceres
left a comment
There was a problem hiding this comment.
Thanks for your patience on this, @niklasl. Over a year waiting for a review is not OK, and I'm sorry about that.
Reviewing this fresh, the :has() concern from the earlier review is no longer relevant: :has() has been baseline since December 2023 and is supported in all browsers we target.
The concern about relying on fixup.js's input[name='color-scheme'] structure is valid in principle, but the alternative is doing nothing, which means dark mode remains broken for syntax highlighting and linked SVGs. That's not acceptable. Additionally, the W3C team coordinates closely with us on tr-design changes, so we shouldn't be overly concerned about them changing fixup.js's structure without checking with us first.
The code is clean, well-commented, and the CSS variable deduplication is a nice improvement on its own. The example file is helpful for testing.
Approving this. Thank you for contributing.
|
@marcoscaceres Thank you! I'm glad this was possible to move forward with. |
Syntax highlighting already works with automatic preferences, but has not played well with neither default (no dark mode) settings, nor worked with the manual scheme toggle. (See also #4871.)
This fixes that using CSS (so that default behavior works without JS).
SVG behavior is by default based on user-agent preferences, and has therefore also not played well with the manual toggle. With this change, that is now handled by setting
color-scheme: lightordarkon the body element, based on the sidebar-provided manual scheme toggle.If no meta element indicating dark color-scheme support is present, light mode is set on the body. This instructs SVGs to render in light mode when embedded in documents with no dark mode support, even when the user agent indicates dark mode. (The
color-schemeCSS property can of course still be set to other values for various sections in a document, if so desired.)A darkmode example document is also added, containing syntax-highlighted code and embedding an SVG document supporting light/dark color-scheme preferences.