Skip to Content
  • Website
Codsen
  • Home
  • Open Source
  • Articles
  • About

Importing SVG in Remix MDX

by Roy Revelt   ·   posted on Monday, 20 June 2022   ·   jstsremixmdx

  • the top
  • NATIVE MARKD…
  • IMPORTING SVG…
  • A DEDICATED…
  • ACCESSIBILITY
  • TAKEAWAY

A decade ago, Chris Coyier from CSS-Tricks describedopens in a new tab ways to consume SVG, which can be distilled into two groups: to link and to embed.

Fast forward to 2022, the market has shifted from WordPress+PHP to React+TypeScript, but the same dilemma “to link or to embed?” still applies because, at the bottom of it, we’re still dealing with the same HTML and CSS as we did a decade ago.

So what’s the best way to import SVG in MDX?


The answer depends. Do you want to style a given SVG differently per dark/light theme? Also, do you use any raw <text> with custom fonts inside SVG?

❔ Native markdown ways

Native markdown notation can import images (including SVG) like this:

![Various layouts on codsen.com website](/images/codsen-article-017-layouts.svg)

In Remix, you’d put the SVG file into /public/images/, and it would become available in Remix under the /images/* path.

This approach does work, but you don’t inherit any CSS from the upper scope:

  • it’s impossible to tap into class="dark" at the root (in my case, remix-themesopens in a new tab sets the current theme’s class on <html> — if <html class=""> makes you cringe too, I already raised a GH ticketopens in a new tab to move to data-* attribute — but remix-themes is still a great plugin)
  • not possible to reference the CSS variables inside the SVG file
  • also impossible for SVG <text> elements to inherit the text styles (relevant considering custom fonts and dark/light themes)

Theoretically, the benefits would be: browser-side caching per file, which is DRY.

❌ Importing SVG directly in MDX

Don’t import SVG files directly in MDX:

import * as Layouts from "../../../public/images/codsen-article-017-layouts.svg";
...
<Layouts/>

or

import Layouts from "../../../public/images/codsen-article-017-layouts.svg";
...
<Layouts/>

It won’t work in Remix.

✅ A dedicated TSX component

The most flexible solution is to create a .tsx component for each SVG. It would end up bundled (so, an “embed” approach) and Remix would pre-fetch it along everything else. In MDX, you’d import it as normal:

import { Article017Layouts } from "~/components/svg/017-layouts.tsx";

But before I show the component’s code — the accessibility...

Accessibility

Use SVGRopens in a new tab converter to convert SVG into TSX. There might be a few bits missing.

The first one is <title>. MDN describesopens in a new tab the solution quite vaguely (as always), but the gist of it is to use <title>+<desc> and to nest it inside <svg> and it must be the first nested child element for backwards compatibility with SVG 1.1.

The aria-labelledby is normally used to link the element to the describing elements, but we can go belt-and-braces and point the aria-labelledby to <title> by its id:

// app/components/svg/017-layouts.tsx
import type { SVGProps } from "react";

export const Article017Layouts = (props: SVGProps<SVGSVGElement>) => (
 <svg
 xmlns="http://www.w3.org/2000/svg"
 viewBox="0 0 738 581.98"
 aria-labelledby="codsen-article-017-layouts"
 role="img"
 {...props}
 >
 <title id="codsen-article-017-layouts">
 Various layouts on codsen.com website
 </title>
 <desc>
 Codsen.com website uses various layouts: absolutely centred-one like on the root home page, two-column like at Open Source root, styled with background images like in login page, also different arrangements of the sidebar, both left and right.
 </desc>
 ...

Also, add role="img" (MDN referenceopens in a new tab).

Theoretically, aria-label could be used instead of <title> but TPGiopens in a new tab and many other trusted sources use the <title>.

With these measures in place, we should be solid accessibility-wise.

Takeaway

I prefer to create TSX components for each SVG and bundle them up inline. It allows the most freedom to style them via CSS: from dark/light theming to SVG inheriting font styling, so SVG <text> elements look consistent with the rest of the page.

↑ back to top
older newer

Copyright

All rights reserved © Roy Revelt 2026
All our open source packages are under MIT licenceopens in a new tab

Activities

🐛 See a bug? Raise an issueopens in a new tab
💘 Check out the Indiewebopens in a new tab and Libera manifestoopens in a new tab