One family, hairline weight
Fifty-six icons drawn to the frame's own line weight. Click any of them to copy its SVG.
01
Rules
viewBox="0 0 24 24", always. Artwork sits on a 24px grid with roughly 2px of clear space, so icons optically match at any size.fill: none; stroke: currentColor. Never a filled or duotone icon — the weight is the point, and a filled glyph is heavier than every line on the page..icon classes handle this — do not set stroke-width per icon.stroke-linecap: round; stroke-linejoin: round. The only rounded thing in the system, and only because a butt cap at 1.4px reads as a chip in the line.currentColor and nothing else. An icon inherits from its context — muted in chrome, accent when the row is active. Never a hardcoded fill.02
The set
Click to copy. Each one comes back as a complete <svg class="icon"> element, ready to paste.
Interface
Action
Status
Data
Domain
03
Sizes
.icon .sm / default / .lg / .xl / .hair
.sm · 0.85rem
default · 1.05rem
.lg · 1.5rem
.xl · 2.2rem
.hair · notches
The stroke weight steps down as the icon grows. A 1.4px stroke that looks right at 17px looks coarse at 35px — this is the same reason headings are set at weight 300 while small labels are at 400.
In context
Verified
Updated 4 min ago
04
Drawing a new one
The set will not cover everything. When you add to it, match these and it will sit down with the rest.
- Draw on the 24px grid at whole and half pixels. A path at
x=7.3renders blurry at 17px. - Keep the extremities at 3 and 21 — roughly 2px of clear space inside the box. An icon that fills its box looks larger than its neighbours.
- Use one path where the shape allows, and combine sub-paths with
Mrather than adding elements:d="M4 7h16M4 12h16". - No
fill, nostroke-width, nostrokeon the paths — all three come from.icon. - Test at 0.85rem before you commit. Detail that vanishes at small size is detail that should not be there.
- Give it an
aria-hidden="true"when a text label sits beside it, and anaria-labelon the button when it does not.
<!-- decorative: the label carries the meaning -->
<button class="btn ghost">
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v12M7 11l5 5 5-5M4 20h16"/></svg>
Export
</button>
<!-- icon only: the button carries the meaning -->
<button class="icon-btn" aria-label="Export">
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v12M7 11l5 5 5-5M4 20h16"/></svg>
</button>