A border is composed rather than chosen: one structural class sets where it sits, and width, style and colour classes each modify a single concern. That is why the system has no — it would fuse two decisions into one name, and then need duplicating for every other combination. The token values behind these classes are on the Tokens page.
Structure
A structural class sets the position. On its own it draws , solid, in .
All sides
Top
Bottom
Left
Right
<div class="border">All sides</div>
<div class="border-top">Top only</div>
| Class | Where it draws |
|---|---|
| Every side — cards, panels, anything enclosed | |
| Above the element, so it reads as a separator from what precedes it | |
| Below, the usual rule between stacked article rows | |
| Beside, for an aside or editor's note set off from the column | |
| Beside, on the trailing edge |
Width
Width is a separate class from position, so any thickness can sit on any side.
Small — the default
Medium
Large
<div class="border border-m">Medium on all sides</div>
| Class | Token | Value and use |
|---|---|---|
| 1px (0.0625rem) — the default, and what almost everything on the site uses | ||
| 1.5px (0.09375rem), for a rule that needs to register as deliberate | ||
| 3px (0.1875rem). Nothing in the shipped system uses it; it is there for emphasis a page might need |
Widths are declared in rem, not pixels, so a border thickens with the reader's browser zoom and root font-size setting rather than staying pinned to a device pixel.
Style
Style is the third axis, and it carries meaning: a border's pattern says how settled the thing inside it is.
Solid — the default
Dashed
Dotted
<div class="border border-dashed">Dashed</div>
| Class | Reads as |
|---|---|
| Settled and structural — the default | |
| Provisional, which is why it suits drafts and empty states | |
| Lighter still, for a slot that is waiting on content |
Colour
Border colours are semantic tokens, so they re-resolve in dark mode without the element knowing.
Primary — the default
Secondary
Faded
<div class="border border-faded">Subtle</div>
| Class | Token | Use |
|---|---|---|
| Structural edges that define a shape. It resolves to the text colour, so it inverts with the theme | ||
| Decorative rules, where the line is not load-bearing | ||
| Hairlines — a division you should feel rather than see |
Radius
Radius has no utility classes. Apply the token in CSS.
2xs — 2px
xs — 4px
s — 6px
m — 10px
l — 16px
xl — 24px
Pill
border-radius: var(--radius-m);
| Token | Value | Use |
|---|---|---|
| 2px | Barely softened — labels and small badges | |
| 4px | Tags and small controls | |
| 6px | Inputs and buttons | |
| 10px | Cards | |
| 16px | Panels and dialogs | |
| 24px | Large surfaces that need a soft edge | |
| 999px | Chips and badges, where the shape is fully rounded |
Composing
Each class modifies one concern, so they stack without fighting.
Top, medium, dashed, secondary
Bottom, large, primary
All sides, faded, dotted
<div class="border-top border-m border-dashed border-secondary">
Top, medium, dashed, secondary
</div>
Rules
- Never write a class that fuses two concerns. looks convenient and then has to be duplicated for every other combination; the composable set already covers all of them.
- Never hardcode a border value. Width, colour and radius are all tokens, and a literal
1px solid #000will not follow the theme into dark mode. - Reach for first. Most divisions on this site want to be felt rather than seen; primary ink is for edges that define a shape.