mermaid-js / mermaid

Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown
https://mermaid.js.org
MIT License
71.56k stars 6.48k forks source link

Light mode/dark mode auto switching. #2644

Open ioquatix opened 2 years ago

ioquatix commented 2 years ago

It's possible (supported in Chrome but not Safari) to use prefers-color-scheme in SVG documents.

With careful styling, this can be used to achieve diagram styling which responds to user preference.

As a fallback, we can detect changes to prefers-color-scheme and refresh SVGs.

This would make the out-of-the-box light/dark styling much more seamless. As of now, the experience is less than ideal and the presentation of diagrams in a website which uses prefers-color-scheme is poor/unusable.

Would this be of interest?

sidharthv96 commented 2 years ago

In mermaid.live, we are currently switching the theme in config based on the color scheme.

ioquatix commented 2 years ago

Yes, it's a reasonable approach for browsers which don't support prefers-color-scheme in SVG documents. Eventually however I believe it will be supported in all browsers.

Can you explain how someone can integrate mermaid.live to achieve this? Thanks!

hemeroc commented 1 year ago

@sidharthv96 I would also be interested in how mermaid.live does it

myl7 commented 4 months ago

IMO it is kinda more complicated.

First, websites have various methods to switch light/dark mode. In addition to media query prefers-color-scheme, class dark is also widely used to toggle it, e.g., in Next.js, so that users can override the browser default. It is hard for Mermaid to choose one (or maybe we need lots of buttons for every methods).

Second, embedding styles for auto light/dark mode switching in SVG documents doesnot always work. E.g., after image optimization of Next.js / Astro, SVGs are loaded via <img src="..."> and thus cannot switch light/dark mode with styles. Only loading SVGs by embedding them as HTML elements can make the styles work.

Anyway, if you use class dark for dark mode and embedded SVGs as HTML elements, you can replace the content of the second <style> element in SVG documents as https://gist.github.com/myl7/c93d000876ec76da8d23b0ccc9cbcb6e to implement auto light/dark mode switching. Ones using media query prefers-color-scheme can modify the CSS correspondingly.

welpo commented 1 month ago

As a simple solution to support both prefers-color-scheme and a manual toggle, I used the invert filter targeting mermaid diagrams (demo):

[data-theme='dark'] .mermaid {
    filter: invert(0.88);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme='light']) .mermaid {
        filter: invert(0.88);
    }
}

This CSS does two things:

  1. It applies an invert filter to diagrams when a data-theme='dark' attribute is set on an ancestor element (my theme switcher updates the html tag).
  2. It also applies the invert filter when the user's system is set to dark mode (prefers-color-scheme: dark), unless a light theme is explicitly set.

Note: I'm using invert(0.88) instead of invert(1) because a full invert looked too harsh to my eyes —different values will work better on different websites.

Hope that helps!