Dark mode with web standards<br>Jun 12, 2026<br>Dark mode with web standards
Respecting the user’s OS setting is straightforward: use the prefers-color-scheme media query in CSS. Arguably, that isn’t enough: users should also be able to customise their choice on a per-site basis. A user might want dark mode for the UI of an application, but light mode for reading long-form text on content-heavy sites, for example.
We need to:
Support the user’s system setting as the default for when the user lands on our website for the first time
Allow the user to override their system setting with a toggle in our application.
The color scheme of a web page can be set either via a HTML meta tag in the of the document or via the CSS color-scheme property on the html element. It can take time for CSS to load on slow connections, so using the meta tag is the recommended approach. When a user lands on your website for the first time, respect their system preference by setting . To override the OS setting via a control in your web app or site, use JavaScript to update the content attribute value to light to force light mode, dark to force dark mode, or light dark to revert back to the OS setting.
const metaTag = document.querySelector('[name="color-scheme"]');
const savedScheme = localStorage.getItem("colorScheme");<br>if (savedScheme) {metaTag.setAttribute('content', savedScheme);}
btnlight.addEventListener('click', function() {<br>metaTag.setAttribute('content', 'light');<br>localStorage.setItem("colorScheme", "light");<br>});<br>btndark.addEventListener('click', function() {<br>metaTag.setAttribute('content', 'dark');<br>localStorage.setItem("colorScheme", "dark");<br>});<br>btnsystem.addEventListener('click', function() {<br>metaTag.setAttribute('content', 'light dark');<br>localStorage.removeItem("colorScheme");<br>});
What does the color-scheme affect?
Colors, gradients, or images set via the light-dark() CSS function
System colors like Canvas and CanvasText
Scrollbar colors
The default colors of HTML elements like buttons
iframes styles (so long as the iframe document has opted in via the meta tag)
SVG’s that make use of light-dark() or prefers-color-scheme
What doesn’t color-scheme affect?
There’s an unfortunate disconnect between color-scheme and the prefers-color-scheme media query. prefers-color-scheme reflects the OS settings — regardless of the color-scheme value. If you’re providing an in-page toggle that implements dark mode, you can’t adopt the prefers-color-scheme media query.
The following code is not be impacted by color-scheme:
picture><br>source srcset="logo-dark.png" media="(prefers-color-scheme: dark)" /><br>source srcset="logo-light.png" media="(prefers-color-scheme: light)" /><br>img src="logo-light.png" alt="Product logo" /><br>picture>
Other than making use of a background-image, there’s sadly not an equivalent approach to the element that references the color-scheme.
There are two exceptions where color-scheme will affect the prefers-color-scheme media query:
iframes
SVG
Below are two iframes that show the same document. The document inside the iframe is making use of the prefers-color-scheme media query.
iframe style="color-scheme: light;" src="/example.html">iframe><br>iframe style="color-scheme: dark;" src="/example.html">iframe>
As you can see in the above example, the @media (prefers-color-scheme: dark) styles are being applied when color-scheme: dark is used in the parent document.
The same principle applies to SVG. Here’s the content of an .svg file:
svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><br>style><br>circle {<br>fill: rgb(40,40,40);
@media (prefers-color-scheme: dark) {<br>circle {<br>fill: rgb(216, 216, 216);<br>style><br>circle cx="50" cy="50" r="50" /><br>svg>
img style="color-scheme: light;" src="/circle.svg" alt=""><br>img style="color-scheme: dark;" src="/circle.svg" alt="">
Some Safari caveats
Support for the prefers-color-scheme media query within SVG was added in Safari 27, but color-scheme does not affect the media query (see bug report)
Support for the prefers-color-scheme media query within iframes was added in Safari 27 and the color-scheme of the parent document does override it, as it should 🎉. However, other bugs remain (see bug report)
Using light-dark() with images and gradients
The light-dark() function was originally limited to colors. It can now be used for gradients and images (as of Chrome/Edge version 150, Firefox version 150, and a forthcoming version of Safari).
.bg-gradient {<br>background-image: light-dark(linear-gradient(15deg, #b9b6ff, #308dc6), linear-gradient(15deg, #6b7495, #001339));
div class="bg-gradient" style="color-scheme: light;">div><br>div class="bg-gradient" style="color-scheme: dark;">div>
It’s also possible to switch between a single solid color and a gradient, depending on the color-scheme.
.bg-grad-solid {<br>background-image: light-dark(linear-gradient(15deg, #b9b6ff, #308dc6), image(#001339));
Images
.bg {<br>background-image: light-dark(url(/lightmode.avif),...