Skip to content

Instantly share code, notes, and snippets.

@privatenumber
Last active October 22, 2024 05:40
Show Gist options
  • Save privatenumber/0b3db759ca8c90103360603ff3d49893 to your computer and use it in GitHub Desktop.
Save privatenumber/0b3db759ca8c90103360603ff3d49893 to your computer and use it in GitHub Desktop.
Light/dark mode SVG image

Warning

This no longer seems to work. And GitHub has added built-in support this: https://github.com/stefanjudis/github-light-dark-image-example#a-test-for-lightdark-mode-images-using-picture

Light/Dark image in GitHub markdown

This gist demonstrates how a light/dark-mode image can be rendered in GitHub markdown. The image of the square below will be dark-blue when your computer prefers dark-mode, and will be bright-yellow if your computer prefers light-mode.

How does it work?

It leverages SVG foreignObject to use the CSS media query prefers-color-scheme: dark to determine which element to show.

In this case, it has two image assets (light & dark versions) Base64'd, but can probably be replaced with a SVG too.

Caveats

  • Toggling light/dark-mode is not reactive. After toggling the system setting, reload the page. If it doesn't work, try checking "Disable cache" in the Chrome devtools Network tab.
  • There cannot be external assets (eg. <img> tag referencing an external file). Use Base64 instead.

Demo

Update

GitHub Markdown now supports an official way to toggle between two images in light/dark mode.

Display the source blob
Display the rendered blob
Raw
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml">
<style>
.light { display: block; }
.dark { display: none; }
@media (prefers-color-scheme: dark) {
.light { display: none; }
.dark { display: block; }
}
</style>
<img class="light" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////2wBDAf//////////////////////////////////////////////////////////////////////////////////////wAARCABkAGQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAL/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFgEBAQEAAAAAAAAAAAAAAAAAAAED/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AsBmoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9k=" />
<img class="dark" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////2wBDAf//////////////////////////////////////////////////////////////////////////////////////wAARCABkAGQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAL/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//2Q==" />
</div>
</foreignObject>
</svg>
@pboling
Copy link

pboling commented Apr 12, 2022

This solution doesn't seem to work at all for me. I always see the blue, no matter the system dark mode setting or the Github dark mode setting. I've tried many variations, but can't get anything to fully work:
https://gist.github.com/pboling/3bd9a0004b8fc010c0d7c523fecee832

@privatenumber
Copy link
Author

Works fine for me.

Light Dark

@codingedgar
Copy link

did not work on iOS safari, but it did after login to comment this (???🙃)

@heaths
Copy link

heaths commented Oct 18, 2024

Not working in Safari 18.0.1, but is on Edge 131.0.2889.0.

@privatenumber
Copy link
Author

@heaths
Copy link

heaths commented Oct 19, 2024

That's good to know. Thank you. I knew about the anchors, but it seems those are being deprecated. That said, in these cases we have SVGs that only vary based on the @media queries within embedded <style>sheets. I'd hate to have to duplicate the entirety of the SVGs just to select one over another when 99.999% of the content is exactly the same.

I did file a feedback issue with Apple Feedback citing this gist and a few other repros. FWIW, GitHub.com is sending a Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox header so it should work, and does work for me in Edge/Chromium e.g., the preview pane in VSCode renders correctly on a dark theme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment