Install
$ agentstack add skill-jpoindexter-typography-skills-color-and-icon-fonts ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
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-paletteworks rather than shipping a
second file.
7. Output format
Purpose:
Technique:
because
Fallback (no COLR support): — acceptable:
Fonts-blocked behaviour:
A11y: decorative → aria-hidden | meaningful →
Contrast at worst point:
Palette themable:
Payload: KB for 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-paletteand
@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).
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jpoindexter
- Source: jpoindexter/typography-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.