Colour and icon fonts
Two capabilities the rest of the pack assumes away: type that carries more than
one colour, and glyphs that carry non-letter meaning. Both are font
technology, both have sharp accessibility edges, and both are chosen far more often
than they should be.
1. When to invoke
- Type must render in more than one colour, with gradients, or as a 3D/layered effect.
- Choosing between an icon font and inline SVG.
- Emoji rendering, sizing, or weighting.
- A colour font renders as flat black in some browsers.
- Icons or emoji are announced wrongly by a screen reader.
Do not invoke for ordinary text colour (that's CSS color) or for choosing a
text face (typeface-selection).
2. Required context
- What the colour is doing — brand expression, information, or decoration.
Only the first two usually justify the cost.
- Which browsers must render it correctly, and what the acceptable degradation is.
- Whether the glyphs are decorative or meaningful (drives the a11y treatment).
- Whether the text must remain selectable, searchable, and translatable.
- Icon count, and whether icons change at runtime.
3. Invariant principles
- Colour fonts degrade, they don't fail — but the degradation is the design
decision. Plan what the flat-colour fallback looks like, because some readers
will only ever see that.
- Never let colour carry meaning alone. Same rule as everywhere else; a colour
font doesn't exempt you from WCAG 1.4.1.
- Icons that carry meaning need an accessible name; icons that are decorative
must be hidden from assistive technology. There is no third option.
- A glyph is not a picture to a screen reader. An icon-font character is
usually announced as a meaningless codepoint from the Private Use Area, or as
nothing at all.
- Layered type must stay legible in one colour. If the layers only resolve into
readable letters when all colours are present, the fallback is illegible.
4. Context-dependent heuristics
Layer fonts vs. colour fonts
Stocks: they are different but "effectively work towards the same goal: to move
beyond 'flat' colors when setting type."
Layer fonts are ordinary font files that "break out different layers into
styles." You duplicate the text, set each copy in a different style, and overlay
them — each layer in its own colour. Chouquet's Lustik uses a Back style of
hand-drawn squares and a Front style of abstract shapes that only read as letters
once combined. Clarke's Rig Shaded ships Face, Extrude, Shadow, and two Shading
styles that build a three-dimensional object. Blend modes on the layers extend this
further.
- Pros: total control per layer; works anywhere; each layer is a normal font.
- Cons: duplicated text nodes (an accessibility and DOM problem on the web),
brittle alignment, and the text is repeated for screen readers unless hidden.
- On the web: acceptable for a one-off display headline; not for body or UI. Mark
all but one layer
aria-hidden="true".
Colour fonts keep everything in one file — no duplicated text — at the cost of
per-layer control.
| Format |
State in 2026 |
| COLRv1 |
The one to use. Paint graph with linear/radial/sweep gradients, transforms, compositing, blending, and variation data for the colour construction itself — so variable colour fonts are real. Renders in Chromium, Firefox, Samsung Internet. Safari falls back to a single solid colour. |
| OT-SVG |
Avoid for new work. Chromium has stated it will never support it, and Firefox has signalled it may drop it. |
| sbix / CBDT (bitmap strikes) |
Raster; resolution-bound. Mostly emoji legacy. |
font-palette is the reason COLR matters. It lets a page select a palette from
a colour font, and @font-palette-values lets you override individual entries or
define your own:
@font-palette-values --brand {
font-family: "Nabla";
override-colors: 0 #1a1a1a, 1 #e63946;
}
.headline { font-family: "Nabla"; font-palette: --brand; }
This is COLR-only. It means one font file can be re-themed per brand or per dark
mode without shipping another file.
Icon fonts vs. SVG
Default to SVG. Icon fonts were a workaround for an era without good SVG
support, and they carry real defects:
| Icon font problem |
Consequence |
| Glyphs live in the Private Use Area |
Screen readers announce garbage or nothing |
| Fails as a font failure |
Font blocked/slow → missing or tofu icons, not degraded ones |
| Single colour only (unless COLR) |
No multi-tone icons |
| Anti-aliased as text |
Icons shift with font smoothing, not pixel-tuned |
| Whole set ships as one file |
Pay for 300 icons to use 12 |
Choose an icon font only when you genuinely need glyph behaviour — icons inline in
text that must inherit font-size, color, and baseline alignment automatically,
across a very large icon set. Then:
aria-hidden="true" on the glyph, with a real text label adjacent, or
role="img" plus aria-label.
- Never put meaning only in the glyph.
- Provide a fallback so a failed font load doesn't erase the UI.
Emoji. Stocks' point in §89 is that icons and symbols "are like type — and often
are fonts," and they behave like type: Noto Emoji ships weights whose stroke
thickness changes to suit context. Practical notes: emoji render per-platform and you
do not control the artwork; they carry a screen-reader name that is often verbose
(🎉 → "party popper"); and they should never be the sole carrier of meaning or state.
5. Failure patterns
| Pattern |
Cause |
Fix |
| Colour font renders flat black in Safari |
COLRv1 unsupported there |
Design the single-colour fallback deliberately |
| Colour font renders flat everywhere |
OT-SVG in Chromium |
Use COLRv1 |
| Layered headline is illegible without colour |
Layers only resolve when combined |
Ensure one layer carries the letterform |
| Screen reader reads the headline three times |
Duplicated layer text nodes |
aria-hidden on all but one |
| Icons vanish on slow connections |
Icon font failed to load |
SVG, or a fallback |
| Screen reader says "private use area 61489" |
Icon glyph with no accessible name |
aria-hidden + text label, or role="img" + aria-label |
| Icon-only button unusable by keyboard/AT |
No accessible name |
Add one |
| 400 KB icon font for 12 icons |
Whole set shipped |
SVG sprite or subset |
| Emoji means "done" and nothing else does |
Meaning carried by glyph alone |
Add text |
| Colour font can't be re-themed for dark mode |
Palette baked in |
font-palette / @font-palette-values |
6. Evaluation procedure
- State what the colour or icon is for. Decorative → hide it from AT.
Meaningful → it needs a text equivalent.
- Render in a browser without COLRv1 support (Safari) and confirm the flat
fallback is acceptable, not broken.
- Render with fonts blocked entirely. Icons and layered type must not take the
interface with them.
- Run a screen reader over it. Nothing should be announced as a codepoint, and
nothing meaningful should be silent.
- Check contrast of the rendered result — gradients mean the ratio varies across
the glyph; test the worst point.
- Grayscale it. Does anything stop making sense?
- Weigh the payload against the number of glyphs actually used.
- If re-theming is needed, confirm
font-palette works rather than shipping a
second file.
7. Output format
Purpose: <brand expression | information | decoration>
Technique: <layer font | COLRv1 | OT-SVG ✗ | bitmap | SVG | icon font>
because <reason>
Fallback (no COLR support): <what renders> — acceptable: <yes/no>
Fonts-blocked behaviour: <what renders>
A11y: decorative → aria-hidden | meaningful → <accessible name>
Contrast at worst point: <ratio>
Palette themable: <font-palette | baked in>
Payload: <n> KB for <n> glyphs used
8. Examples
Brand wants a gradient, dimensional headline face.
Two routes. A layer font like Rig Shaded gives per-layer control — Face,
Extrude, Shadow — but on the web it means duplicated text nodes, so all but one
copy needs aria-hidden and the alignment is brittle at fluid sizes. A COLRv1
colour font keeps it to one text node with real gradients, and font-palette lets
dark mode re-theme it without a second file. Recommending COLRv1 — but the
deciding question is Safari, which falls back to a single solid colour. Design that
flat state first and confirm the brand still holds; if it doesn't, the effect is
wrong for this surface regardless of technique.
"Should we use an icon font or SVG for our 40 product icons?"
SVG. Forty icons doesn't justify the icon-font tradeoffs: PUA codepoints that
screen readers mangle, icons disappearing entirely if the font fails, single-colour
only, and shipping the whole set to use a subset. The one case that would flip this
is icons inlined mid-sentence that must inherit size, colour, and baseline
automatically — that's genuine glyph behaviour and SVG handles it worse. Not the
case here.
9. Counterexamples
- ❌ "Use an OT-SVG colour font for the hero." — Chromium has said it will never
support OT-SVG. Most of your traffic gets flat colour.
- ❌ "Colour fonts degrade gracefully, so no fallback design is needed." — The
fallback is a design state; Safari users only see it.
- ❌ "The icon is obvious, it doesn't need a label." — Obvious to sighted users
looking at it. A screen reader gets a codepoint.
- ❌
aria-hidden="true" on an icon that is the button's only content. — Now the
button has no accessible name at all.
- ❌ "We'll ship two font files for light and dark palettes." —
font-palette and
@font-palette-values re-theme one COLR file.
- ❌ Layering four copies of a headline in the DOM with no
aria-hidden. — The
headline is read four times.
- ❌ "✅ means the step is complete." — with no text saying so.
10. Source citations
- Stocks, Universal Principles of Typography — §89 "icons & symbols are like type
— and often are fonts" (Noto Emoji's weights changing stroke thickness to suit
context); §90 "expand your palette with layer fonts & color fonts" — layer fonts
and colour fonts "effectively work towards the same goal: to move beyond 'flat'
colors when setting type"; layer fonts "break out different layers into styles" so
you "duplicate our text box and select a different style for each one"; Chouquet's
Lustik (Back/Front styles resolving into legible characters) and Clarke's Rig
Shaded (Face, Extrude, Shadow, Shading building a three-dimensional object);
blend modes; colour fonts keeping all options in one file.
- Current standards take precedence on support. COLRv1 renders in Chromium,
Firefox, and Samsung Internet; Safari falls back to a single solid colour.
Chromium has stated it will not support OpenType-SVG; Firefox has signalled it may
drop it. COLRv1 carries a paint graph (linear/radial/sweep gradients, transforms,
compositing, blending) plus variation data for the colour construction itself.
MDN —
font-palette,
@font-palette-values.
- WCAG 2.2 §1.1.1 (non-text content), §1.4.1 (use of colour), §1.4.3 (contrast).
1---2name: color-and-icon-fonts3description: Use when type needs to be more than one flat colour, or when glyphs carry non-letter meaning — layer fonts, colour fonts (COLRv1, OT-SVG, bitmap), CSS font-palette, icon fonts, emoji. Also use when deciding between an icon font and SVG, when a colour font renders as flat black, or when emoji or icons break in a screen reader.4---56# Colour and icon fonts78Two capabilities the rest of the pack assumes away: type that carries **more than9one colour**, and glyphs that carry **non-letter meaning**. Both are font10technology, both have sharp accessibility edges, and both are chosen far more often11than they should be.1213## 1. When to invoke1415- Type must render in more than one colour, with gradients, or as a 3D/layered effect.16- Choosing between an icon font and inline SVG.17- Emoji rendering, sizing, or weighting.18- A colour font renders as flat black in some browsers.19- Icons or emoji are announced wrongly by a screen reader.2021**Do not** invoke for ordinary text colour (that's CSS `color`) or for choosing a22text face (`typeface-selection`).2324## 2. Required context2526- **What the colour is doing** — brand expression, information, or decoration.27 Only the first two usually justify the cost.28- **Which browsers must render it correctly**, and what the acceptable degradation is.29- Whether the glyphs are **decorative or meaningful** (drives the a11y treatment).30- Whether the text must remain **selectable, searchable, and translatable**.31- Icon count, and whether icons change at runtime.3233## 3. Invariant principles3435- **Colour fonts degrade, they don't fail — but the degradation is the design36 decision.** Plan what the flat-colour fallback looks like, because some readers37 will only ever see that.38- **Never let colour carry meaning alone.** Same rule as everywhere else; a colour39 font doesn't exempt you from WCAG 1.4.1.40- **Icons that carry meaning need an accessible name**; icons that are decorative41 must be hidden from assistive technology. There is no third option.42- **A glyph is not a picture to a screen reader.** An icon-font character is43 usually announced as a meaningless codepoint from the Private Use Area, or as44 nothing at all.45- **Layered type must stay legible in one colour.** If the layers only resolve into46 readable letters when all colours are present, the fallback is illegible.4748## 4. Context-dependent heuristics4950### Layer fonts vs. colour fonts5152Stocks: they are different but "effectively work towards the same goal: to move53beyond 'flat' colors when setting type."5455**Layer fonts** are ordinary font files that "break out different layers into56styles." You duplicate the text, set each copy in a different style, and overlay57them — each layer in its own colour. Chouquet's *Lustik* uses a Back style of58hand-drawn squares and a Front style of abstract shapes that only read as letters59once combined. Clarke's *Rig Shaded* ships Face, Extrude, Shadow, and two Shading60styles that build a three-dimensional object. Blend modes on the layers extend this61further.6263- **Pros:** total control per layer; works anywhere; each layer is a normal font.64- **Cons:** duplicated text nodes (an accessibility and DOM problem on the web),65 brittle alignment, and the text is repeated for screen readers unless hidden.66- **On the web:** acceptable for a one-off display headline; not for body or UI. Mark67 all but one layer `aria-hidden="true"`.6869**Colour fonts** keep everything in one file — no duplicated text — at the cost of70per-layer control.7172| Format | State in 2026 |73|---|---|74| **COLRv1** | The one to use. Paint graph with linear/radial/sweep gradients, transforms, compositing, blending, and **variation data for the colour construction itself** — so variable colour fonts are real. Renders in Chromium, Firefox, Samsung Internet. **Safari falls back to a single solid colour.** |75| **OT-SVG** | Avoid for new work. **Chromium has stated it will never support it**, and Firefox has signalled it may drop it. |76| **sbix / CBDT (bitmap strikes)** | Raster; resolution-bound. Mostly emoji legacy. |7778**`font-palette` is the reason COLR matters.** It lets a page select a palette from79a colour font, and `@font-palette-values` lets you override individual entries or80define your own:8182```css83@font-palette-values --brand {84 font-family: "Nabla";85 override-colors: 0 #1a1a1a, 1 #e63946;86}87.headline { font-family: "Nabla"; font-palette: --brand; }88```8990This is COLR-only. It means one font file can be re-themed per brand or per dark91mode without shipping another file.9293### Icon fonts vs. SVG9495**Default to SVG.** Icon fonts were a workaround for an era without good SVG96support, and they carry real defects:9798| Icon font problem | Consequence |99|---|---|100| Glyphs live in the Private Use Area | Screen readers announce garbage or nothing |101| Fails as a font failure | Font blocked/slow → missing or tofu icons, not degraded ones |102| Single colour only (unless COLR) | No multi-tone icons |103| Anti-aliased as text | Icons shift with font smoothing, not pixel-tuned |104| Whole set ships as one file | Pay for 300 icons to use 12 |105106Choose an icon font only when you genuinely need glyph behaviour — icons inline in107text that must inherit `font-size`, `color`, and baseline alignment automatically,108across a very large icon set. Then:109110- `aria-hidden="true"` on the glyph, with a real text label adjacent, **or**111 `role="img"` plus `aria-label`.112- Never put meaning only in the glyph.113- Provide a fallback so a failed font load doesn't erase the UI.114115**Emoji.** Stocks' point in §89 is that icons and symbols "are like type — and often116are fonts," and they behave like type: Noto Emoji ships weights whose stroke117thickness changes to suit context. Practical notes: emoji render per-platform and you118do not control the artwork; they carry a screen-reader name that is often verbose119(🎉 → "party popper"); and they should never be the sole carrier of meaning or state.120121## 5. Failure patterns122123| Pattern | Cause | Fix |124|---|---|---|125| Colour font renders flat black in Safari | COLRv1 unsupported there | Design the single-colour fallback deliberately |126| Colour font renders flat everywhere | OT-SVG in Chromium | Use COLRv1 |127| Layered headline is illegible without colour | Layers only resolve when combined | Ensure one layer carries the letterform |128| Screen reader reads the headline three times | Duplicated layer text nodes | `aria-hidden` on all but one |129| Icons vanish on slow connections | Icon font failed to load | SVG, or a fallback |130| Screen reader says "private use area 61489" | Icon glyph with no accessible name | `aria-hidden` + text label, or `role="img"` + `aria-label` |131| Icon-only button unusable by keyboard/AT | No accessible name | Add one |132| 400 KB icon font for 12 icons | Whole set shipped | SVG sprite or subset |133| Emoji means "done" and nothing else does | Meaning carried by glyph alone | Add text |134| Colour font can't be re-themed for dark mode | Palette baked in | `font-palette` / `@font-palette-values` |135136## 6. Evaluation procedure1371381. State what the colour or icon is **for**. Decorative → hide it from AT.139 Meaningful → it needs a text equivalent.1402. Render in a browser **without** COLRv1 support (Safari) and confirm the flat141 fallback is acceptable, not broken.1423. Render with **fonts blocked entirely.** Icons and layered type must not take the143 interface with them.1444. Run a screen reader over it. Nothing should be announced as a codepoint, and145 nothing meaningful should be silent.1465. Check contrast of the rendered result — gradients mean the ratio varies across147 the glyph; test the worst point.1486. Grayscale it. Does anything stop making sense?1497. Weigh the payload against the number of glyphs actually used.1508. If re-theming is needed, confirm `font-palette` works rather than shipping a151 second file.152153## 7. Output format154155```156Purpose: <brand expression | information | decoration>157Technique: <layer font | COLRv1 | OT-SVG ✗ | bitmap | SVG | icon font>158 because <reason>159Fallback (no COLR support): <what renders> — acceptable: <yes/no>160Fonts-blocked behaviour: <what renders>161A11y: decorative → aria-hidden | meaningful → <accessible name>162Contrast at worst point: <ratio>163Palette themable: <font-palette | baked in>164Payload: <n> KB for <n> glyphs used165```166167## 8. Examples168169**Brand wants a gradient, dimensional headline face.**170171> Two routes. A **layer font** like Rig Shaded gives per-layer control — Face,172> Extrude, Shadow — but on the web it means duplicated text nodes, so all but one173> copy needs `aria-hidden` and the alignment is brittle at fluid sizes. A **COLRv1**174> colour font keeps it to one text node with real gradients, and `font-palette` lets175> dark mode re-theme it without a second file. Recommending COLRv1 — but the176> deciding question is Safari, which falls back to a single solid colour. Design that177> flat state first and confirm the brand still holds; if it doesn't, the effect is178> wrong for this surface regardless of technique.179180**"Should we use an icon font or SVG for our 40 product icons?"**181182> SVG. Forty icons doesn't justify the icon-font tradeoffs: PUA codepoints that183> screen readers mangle, icons disappearing entirely if the font fails, single-colour184> only, and shipping the whole set to use a subset. The one case that would flip this185> is icons inlined mid-sentence that must inherit size, colour, and baseline186> automatically — that's genuine glyph behaviour and SVG handles it worse. Not the187> case here.188189## 9. Counterexamples190191- ❌ "Use an OT-SVG colour font for the hero." — Chromium has said it will never192 support OT-SVG. Most of your traffic gets flat colour.193- ❌ "Colour fonts degrade gracefully, so no fallback design is needed." — The194 fallback *is* a design state; Safari users only see it.195- ❌ "The icon is obvious, it doesn't need a label." — Obvious to sighted users196 looking at it. A screen reader gets a codepoint.197- ❌ `aria-hidden="true"` on an icon that is the button's only content. — Now the198 button has no accessible name at all.199- ❌ "We'll ship two font files for light and dark palettes." — `font-palette` and200 `@font-palette-values` re-theme one COLR file.201- ❌ Layering four copies of a headline in the DOM with no `aria-hidden`. — The202 headline is read four times.203- ❌ "✅ means the step is complete." — with no text saying so.204205## 10. Source citations206207- Stocks, *Universal Principles of Typography* — §89 "icons & symbols are like type208 — and often are fonts" (Noto Emoji's weights changing stroke thickness to suit209 context); §90 "expand your palette with layer fonts & color fonts" — layer fonts210 and colour fonts "effectively work towards the same goal: to move beyond 'flat'211 colors when setting type"; layer fonts "break out different layers into styles" so212 you "duplicate our text box and select a different style for each one"; Chouquet's213 *Lustik* (Back/Front styles resolving into legible characters) and Clarke's *Rig214 Shaded* (Face, Extrude, Shadow, Shading building a three-dimensional object);215 blend modes; colour fonts keeping all options in one file.216- **Current standards take precedence on support.** COLRv1 renders in Chromium,217 Firefox, and Samsung Internet; **Safari falls back to a single solid colour**.218 Chromium has stated it will not support OpenType-SVG; Firefox has signalled it may219 drop it. COLRv1 carries a paint graph (linear/radial/sweep gradients, transforms,220 compositing, blending) plus variation data for the colour construction itself.221 MDN — [`font-palette`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-palette),222 [`@font-palette-values`](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-palette-values).223- WCAG 2.2 §1.1.1 (non-text content), §1.4.1 (use of colour), §1.4.3 (contrast).