Automatic dark mode for Drawio diagrams using CSS filters

In my latest blog post “Nginx HTTP/3 proxy server displays content from the wrong virtual host,” I included a diagram from Diagrams.net / Drawio, which is an SVG file.

When you export your diagram from Draw.io, you can choose whether you want to apply a light or dark color theme to the exported graphic. I usually choose the light one here so that the diagram fits well with the light default theme of thomas-leister.de. But how do I deal with this in the dark version of my blog? Users automatically see the dark theme if they have set their operating system accordingly. I wondered if there was an easy way to convert the light SVG graphics to dark versions if necessary. After all, CSS now supports filter, right?

Fortunately, I was able to find a simple solution to the problem fairly quickly: “One line - Dark Mode using CSS”. And this is the trick I found:

filter: invert(1) hue-rotate(180deg);

This CSS line first inverts all colors (i.e., from light to dark and vice versa). Black is converted to white (and vice versa), but colors are also inverted. This is not intentional. Therefore, colored content is converted back using a hue-rotate.

I implemented the following in my blog’s CSS stylesheet:

@media (prefers-color-scheme: dark) {
    /* 
    * Invert colors for SVG diagrams
    */
    figure.diagram  img {
        filter: invert(1) hue-rotate(180deg);
    }
}

Only graphics located in an <figure> HTML element of the class diagram are affected by the conversion – and only if the user has selected a dark theme in their operating system settings.

If I now want to embed an SVG drawing in a blog entry, I do so using the following shortcode:

{{< figure src="images/my-drawing.drawio.svg" caption="My description" class="diagram" >}}

And this is what the result can look like (top in dark mode – bottom in light mode):

Example screenshot of a diagram on my blog