Icons are inline SVG elements wrapped in a container class. They inherit colour from the surrounding text, maintain a fixed square aspect ratio, and are accessible by default.
Principles
- Inline SVG only — never use
<img>tags for icons. Inline SVGs allow colour inheritance and eliminate extra HTTP requests. currentColoralways — all icon<path>elements must usefill="currentColor"so the icon inherits the parent's text colour. This keeps icons visually consistent across themes and contexts.- No
xmlns— stripxmlnsandxmlns:xlinkattributes from inline SVGs. They are only needed for standalone files, not inline usage. - Square aspect ratio — icons are always 1:1. Use
viewBoxto define the coordinate system, notwidth/height. - Brand icons only — do not use Material Design, Font Awesome, Heroicons, Feather, or any other third-party icon source. Use the brand icons from
assets/images/svg-icons/. If no icon exists for your need, request one from the design team.
Icon Wrapper
Use to wrap inline SVG icons. This class constrains the icon to a fixed size and enforces the square aspect ratio.
<div class="svg-icn" data-icon="arrow-right">
<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none">
<path d="M5 12h14M12 5l7 7-7 7" fill="currentColor"/>
</svg>
</div>
Properties
| Property | Value | Purpose |
|---|---|---|
width |
1.5rem |
Standard icon size |
height |
1.5rem |
Matches width for square |
display |
flex |
Enables centering |
justify-content |
center |
Horizontal centering |
align-items |
center |
Vertical centering |
aspect-ratio |
1 / 1 |
Enforces square shape |
data-icon attribute
Always include a data-icon attribute with a descriptive name. This makes icons identifiable in code — raw SVG paths are unreadable without it.
<div class="svg-icn" data-icon="chevron-down">...</div>
<div class="svg-icn" data-icon="close">...</div>
<div class="svg-icn" data-icon="search">...</div>
Use lowercase kebab-case for icon names (e.g. arrow-right, chevron-down, external-link).
Icon in Buttons
For icon-only buttons, use on the button and as the SVG wrapper.
<button class="button is-icon" aria-label="Close">
<div class="svg-icn">
<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none">
<path d="M18 6L6 18M6 6l12 12" fill="currentColor"/>
</svg>
</div>
</button>
See the Button documentation for full button modifier details.
SVG Requirements
Every icon SVG must follow these rules before being added to the codebase:
| Rule | Required | Example |
|---|---|---|
fill="currentColor" |
Yes | Inherits text colour from parent |
viewBox attribute |
Yes | viewBox="0 0 24 24" defines the coordinate space |
No xmlns |
Yes | Strip xmlns and xmlns:xlink — not needed inline |
width="100%" height="100%" |
Yes | SVG fills its wrapper; sizing is controlled by the wrapper class |
fill="none" on <svg> |
Yes | Prevents default black fill; paths use fill="currentColor" individually |
| No XML comments | Recommended | Remove <!-- ... --> comments for cleaner code |
Standard viewBox
Use 0 0 24 24 as the default icon grid. If an icon uses a different coordinate system, preserve its original viewBox — do not rescale manually.
Accessibility
- Decorative icons — add
aria-hidden="true"to the SVG when the icon is purely visual and accompanied by text. - Meaningful icons — add
aria-labelto the parent element (e.g. the button) when the icon conveys meaning without visible text. - Icon buttons — always include
aria-labelon the<button>element.
<!-- Decorative: icon next to text -->
<div class="svg-icn" data-icon="check">
<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M20 6L9 17l-5-5" fill="currentColor"/>
</svg>
</div>
<!-- Meaningful: icon button with no visible text -->
<button class="button is-icon" aria-label="Close menu">
<div class="svg-icn">
<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M18 6L6 18M6 6l12 12" fill="currentColor"/>
</svg>
</div>
</button>
Colour
Icons inherit colour through currentColor. To change an icon's colour, change the text colour of its parent — never hardcode a fill value.
<!-- Icon inherits the faded text colour -->
<div class="text-faded">
<div class="svg-icn" data-icon="info">
<svg width="100%" height="100%" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 2a10 10 0 100 20 10 10 0 000-20zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" fill="currentColor"/>
</svg>
</div>
</div>
Icon Shorthand
Use {{icon:name}} in any markdown file processed by the doc generator to render an inline icon. The shorthand is expanded at build time — the actual SVG is read from assets/images/svg-icons/ and injected as a standard wrapper.
{{icon:check}} → renders the check icon
{{icon:arrow-right}} → renders the arrow-right icon
{{icon:t-shirt}} → renders the t-shirt icon
The name must match a key from the icon registry below. If the name is not found, a warning is logged during generation and an HTML comment is output instead.
This shorthand only works in files processed by cms/generator/generate-docs.js — it does not work in standalone HTML pages.
SVG Cleaner Tool
Use the SVG Cleaner to prepare icons before adding them to the codebase. The tool automates the required cleanup:
- Strips
xmlnsattributes - Sets fills to
currentColor(when enabled) - Wraps in with
data-iconattribute (when "Icon" is checked) - Strips XML comments
- Optional minification
For CLI usage:
echo '<svg>...</svg>' | node assets/js/svg-clean.js --current-color --icon --icon-name arrow-right --strip-comments
Naming Conventions
| Convention | Example |
|---|---|
| Lowercase kebab-case | arrow-right, chevron-down |
| Describe the shape, not the function | arrow-right not go-forward |
| Use directional suffixes | chevron-up, chevron-down, chevron-left |
| Use common icon vocabulary | close, search, menu, check, plus, minus |
Rules
| Do | Don't |
|---|---|
Use fill="currentColor" on all paths |
Hardcode hex colours in SVG fills |
| Use to wrap all icons | Use <img> tags for icons |
Include data-icon with a descriptive name |
Leave icons unnamed |
Include aria-hidden="true" on decorative icons |
Omit accessibility attributes |
Include aria-label on icon-only buttons |
Rely on the icon alone to convey meaning |
| Use the SVG Cleaner to prepare icons | Manually edit SVG attributes |
Strip xmlns from inline SVGs |
Keep attributes meant for standalone files |
Use width="100%" height="100%" on SVGs |
Use fixed pixel/rem sizes on the SVG element |
Use fill="none" on the <svg> element |
Omit fill on <svg> (defaults to black) |
| Use wrapper to control icon size | Size icons via width/height on the SVG |
| Check the registry before using any icon | Use external icon libraries as a fallback |
Requesting a New Icon
If you need an icon that is not in the brand icon set:
- Check the brand book — the icon you need may exist under a different name. See the Visual Identity page for the full icon grid.
- Document the request — describe the concept, intended size, and where it will be used
- Submit to the design team — new icons must match the existing style (24x24 grid, single-colour, rounded corners)
- Do not use a placeholder — wait for the brand icon to be designed rather than shipping with a generic substitute
Maintaining a consistent icon language across the site is more important than shipping fast with mismatched icons.