Skip to content

Theme Responsive Graphics

June 5, 2022

Change the interface theme with K (or click the menu on mobile) and see the graphic above adapt

Using SVGs

Some ideas are best conveyed visually. As I designed graphics, flowcharts, and graphs for this site I was annoyed that these graphics ignored user’s theme preference and realized SVGs could be used to solve this problem.

Replace SVG colors with variable values

We can speed up color replacement by using regular expressions for search and replace. This feature is accessible via F, then R in VSCode or Sublime Text and is default behavior in Vim.

Regex for find and replace

(fill|stroke)="((?:[\s\S](?!(fill|stroke)=))+?)"

Search query:
The query above searches for all places in which color the HTML attributes “fill” or “stroke” are used. The attribute and value are stored in capturing groups 1 and 2 respectively.

<path d="M148 200H660.602V246.83H148V200Z"/>
</mask>
<path d="M148 200H660.602V246.83H148V200Z" fill="red" />
<path d="M660.602 245.565H148V248.096H660.602V245.565Z" />
</g>

This query can be paired with a replace expression like class="$1-$2". In the highlighted line above running this replacement would swap fill="red" with class="fill-red" for which we could write a corresponding CSS utility class that ingests a theme variable like var(--red) or in any other flavor of CSS-in-JS.

If you are already using Tailwind CSS this approach is idiomatic, just rewrite the replacement expression to target your existing Tailwind utility classes.

I design almost everything in Figma these days. I’m looking into writing a plugin that can export theme responsive SVGs using a user-inputted color-to-variable-naming map, possibly integrating with Alex Dyakov’s Appearance Plugin.

Inlining SVGs

If we want our site’s styles to apply to SVGs we need to load them in inline. This is trivial with hard-coded HTML and JSX pages, but I ran into an issue doing this when writing posts like this in MDX.

Luckily, libraries like react-inlinesvg exist, enabling us to build custom SVG components to inline and style our vectors with TypeScript and SSR support.

SVG Wrapper Component

An minimal reproduction of my SVG rendering component, provided to the MDX, can be seen below.

import SVG, { Props as SVGProps } from "react-inlinesvg"
import React from "react"
import styled from "styled-components"

const ResetSVG = styled(SVG)`
  height: unset;
  width: 100%;
`

const SVGWrapper = React.forwardRef<SVGElement, SVGProps>((props, ref) => (
  <ResetSVG innerRef={ref} {...props} />
))

SVGWrapper.displayName = "SVG"

export { SVGWrapper as SVG }

Examples

I thought it would be fun to include some examples of responsive graphics below.