Color and icon fonts
Skill jpoindexter/typography-skills/skills/color-and-icon-fonts
Typography skills for AI coding agents — 20 focused skills + a /type router, extracted from 10 canonical typography books and reconciled against WCAG 2.2 and current browser behavior.
npx -y skills add jpoindexter/typography-skills --skill color-and-icon-fontsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 10 days oldThe repository was created 10 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
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.
SKILL.md
11.6 KB, as published. Nobody here has run it
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, orrole="img"plusaria-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-paletteworks 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-hiddenand the alignment is brittle at fluid sizes. A COLRv1 colour font keeps it to one text node with real gradients, andfont-palettelets 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-paletteand@font-palette-valuesre-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).