Marking up colors, revisited with GitHub’s color swatches
Tags: webdev, a11y, html, svg
Published: 2023-01-05 23:21:14

---
title: Marking up colors, revisited with GitHub’s color swatches
published: true
description: Don’t worry, colors are simple! As simple as numbers, dates, names, addresses… uh-oh.
tags: webdev, a11y, html, svg
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4rxx2b5qr5bnd74qhlum.png
---

[I wrote about semantic HTML for colors 5 years ago](https://codepen.io/tigt/post/semantic-html-for-colors), for when a color’s appearance is important content, not just style:

- Design systems’ available color palettes
- Choosing what color of clothing you would like to buy
- Preview swatches for sites about paint
- Probably lots more — colors are pretty important!

My original post suggested a labeled `<input type=color readonly>`, but since then I’ve thought about how that falls short:

- Can’t display [wide-gamut colors](https://matthiasott.com/notes/world-wide-gamut-web), or [managed color](https://github.com/whatwg/html/issues/3400) in general
- Can’t display semitransparency, gradients, patterns, or other fancy swatches
- Can’t nest inside `<a>`, `<button>`, another form field’s `<label>`, etc.
- `readonly` still isn’t allowed on `<input type=color>`… and [the color picker/inspection popup isn’t accessible yet anyway](https://a11ysupport.io/tech/html/input(type-color)_element)

So, my original conclusion’s `<svg>` is probably a better idea. (I’d use my Edit button on that post… [_if I had one_](https://blog.codepen.io/2020/08/28/posts-sunset/).)

Now, those issues are important, but the real reason I’m writing this is much pettier: I used Inspect Element on github.com and got mad about it.

## GitHub’s hex code swatches

GitHub has a feature where if you type a 6-digit hex code in Markdown files/comments/whatever, it displays a color dot of that hex in RRGGBB format:

![Screenshot of GitHub’s rendering the hex code #aa4400. The usual gray box around the &lt;code&gt; element extends to the right to hold a small circle of a dusky brick red.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ug94fqv8oej3vmaonhwj.png)

For example, GitHub’s HTML output if you type `` `#aa4400` `` looks like:

```html
<code>#aa4400
  <span
    class="ml-1 d-inline-block border circle color-border-subtle"
    style="background-color: #aa4400; height: 8px; width: 8px;"
  ></span>
</code>
```

This has problems:

<dl>
<dt>Not exposed accessibly
<dd>Forget text alternatives, right now it’s completely nonexistent to assistive technology

<dt>Too easily overridden
<dd>By Dark/Light Mode browser extensions, <a href="https://css-tricks.com/a-complete-guide-to-dark-mode-on-the-web/">builtin Dark Mode browser support</a>, user styles, etc.

<dt>Invisible under forced colors
<dd><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors"><code>forced-colors</code></a> is the standardized name for features like Windows High-Contrast Mode, which turn off <code>background-color</code> altogether

</dl>

We can fix most of those problems with inline SVG:

```html
<code>#aa4400
  <svg width="8" height="8"
    fill="#aa4400"
    class="ml-1 border circle color-border-subtle"
  >
    <rect width="100%" height="100%"/>
  </svg>
</code>
```

A few notes on the above markup:

- I haven’t exposed it accessibly yet, because that turned out to be [a whole section’s worth of considerations](#accessibly-exposing-the-color)
- No longer needs the `d-inline-block` class (`<svg>` is `inline-block` by default)
- No `style` attribute lets it play nice with strict Content-Security Policies

### But why stop there when we could be perfectionist

GitHub’s current implementation also has what I presume is a bug, where it looks silly inside larger text:

<figure>

![Almost like the earlier screenshot, but while the gray box scales proportionally around the text, the color dot stays 8×8 pixels and awkwardly sits near the bottom — it honestly resembles a colorful punctuation mark.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nfq7n57gotfv7gndxjif.png)

<figcaption><p>Inside an <code>&lt;h1&gt;</code>, for example.</figcaption>
</figure>

SVG’s `width` and `height` attributes can use `em`s to scale the dot with the font size:

```html
<code>#aa4400
  <svg width=".667em" height=".667em"
    fill="#aa4400"
    class="ml-1 border circle color-border-subtle"
  >
    <rect width="100%" height="100%"/>
  </svg>
</code>
```

Heck, you could even replace [GitHub Primer’s utility classes](https://primer.style/css/utilities) with SVG’s builtins:

```html
<code>#aa4400
  <svg width=".667em" height=".667em"
    fill="#aa4400"
    viewBox="-9 -8 17 16" stroke="var(--border-subtle)"
  >
    <circle radius="16"/>
  </svg>
</code>
```

GitHub probably won’t, since once you choose utility classes for something you need to use them _everywhere_ or their core performance promise falls apart[^1], but maybe ***you*** might?

[^1]: Any feature you have to “earn” by adhering to a technology and you shall have no technologies before it is one I distrust. Migrating _away_ from something like Tailwind is suspiciously difficult. (This is my footnote and I can be crankety if I want to.)

### By the way, GitLab does this too

And as usual, GitLab implemented the feature more thoughtfully than GitHub did[^2]. They support [more color syntaxes _and_ transparency](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#colors), it [doesn’t have the `font-size` scaling bug](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/2b5bd61ab9de9b203ff42f23051770585805d5e3/app/assets/stylesheets/framework/gfm.scss#L30-35), and the markup is refreshingly simple:

[^2]: Using GitHub Actions after working in GitLab CI is like disassembling a perfectly good sandwich and making it into sushi. It all eventually goes where you need, but nobody’s happy.

```html
<code>HSLA(540,70%,50%,0.3)
  <span class="gfm-color_chip">
    <span style="background-color: HSLA(540,70%,50%,0.3);"></span>
  </span>
</code>
```

It still breaks with forced colors and dark mode, so maybe the GitLab peeps would be interested in this article anyway. ([I also refactored theirs to be shorter, simpler, and with one less `<span>`](https://codepen.io/tigt/pen/QWBEWpo?editors=1100), because I’m insufferable.)

Speaking of accessibility, there’s something I haven’t addressed…

## Accessibly exposing the color

So, that `<svg>`. What’s its `role`? Its accessible name? Should it be announced at all?

For this specific case, it has a text equivalent right alongside it, and GitHub’s audience is tech-savvier than usual — I can imagine that GitHub may have decided announcing the color dot separately was superfluous.

…but I disagree. Displaying the color adds information for sighted users, hence why the feature exists at all; for the ideal of information parity across disability boundaries, we should try to be equitable.

Since the hex code is already there, a proper text alternative would be the information equivalent of displaying the color dot. Maybe a color name via something like [the ISCC–NBS system](https://en.wikipedia.org/wiki/ISCC%E2%80%93NBS_system)?[^3]

[^3]: There’s a bunch of color naming systems and [even more color naming NPM packages](https://www.npmjs.com/search?q=color%20names), and I’m not qualified to recommend any of them.

Trying [to _explain_ colors to people who can’t see them](https://hub.jhu.edu/2021/08/17/blind-people-understand-color/) isn’t the goal — but [naming a color consistently can be quite useful by itself](https://pubs.acs.org/doi/10.1021/acs.jchemed.1c00664). Not to mention, [blind people may want to know for its own sake](https://austinseraphin.net/2010/06/12/my-first-week-with-the-iphone/)!

```html
<code>#aa4400
  <svg role="img" aria-labelledby="_Z5jdHi6">
    <title id="_Z5jdHi6">Color: “firebrick”</title>
    …
  </svg>
</code>
```

- I’m not 100% sure you need the `role` — the state of the art with inline SVG accessibility has changed a lot recently, [as this StackOverflow question, answer, and interspersed comments show](https://stackoverflow.com/questions/49197524/what-is-the-default-aria-role-for-an-svg).

- Using `<title>` shows up on hover, which helps colorblind folks disambiguate when they need to.

- I’m using `aria-labelledby` because [`aria-label` still isn’t machine translated.](https://heydonworks.com/article/aria-label-is-a-xenophobe/) (Then again, I’m not sure Google/Bing translate inline SVG yet either.)

## I don’t have a real conclusion but here’s a fun fact

When I first started learning about color accessibility, the explanations of what each colorblindness variety sees instead of the “real” colors bothered me — how could they be so sure? While normally I’m happy to leave [“do you and I see the same red” to the philosophers](https://en.wikipedia.org/wiki/Qualia), this was too important for a hand-wavy justification to satisfy me.

Days later, lost and confused from scientific papers about human retinas, the occipital lobe, signal processing, and other complexities around one of the first skills babies learn, I found an answer that was so prosaic it made me laugh: some people are colorblind in only _**one**_ eye.