Atoms
Button
An action on the page, such as saving a Form, opening a Dialog or changing a setting.
Code
<button type="button" class="button"><span>Save changes</span></button>
Why it exists
Most of what a person does on a page, they do through a Button. It is a real <button> because the browser already gives it focus, keyboard use and a role that assistive technology understands, and nothing here replaces those.
Its look comes from two separate choices: prominence says how much attention an action deserves, and intent says what kind of action it is. Keeping them apart means a quiet destructive action and a loud one are the same two ideas, not two more variants to learn.
A 48px hit area is the default at every size, because a target that’s easy to reach helps everyone. A smaller one is a decision a product makes on purpose.
When to use
- For an action: submit, save, open, delete, toggle. Use
<button type="button">(ortype="submit"in a Form). - Not for going somewhere. A Link goes to another page, even when it looks like a Button:
<a class="button">keeps its link role. - Not for one choice among views (a Tab List) or a setting that is on or off (a switch), unless it is a toggle Button.
Rules
- Never colour alone (WCAG 1.4.1): the label says what happens (“Delete project”), or an icon does.
- Every size keeps a 48px hit area (WCAG 2.5.5), unless the product opts into fine-pointer targets. Never below 24px (2.5.8).
- One modifier per axis. Write
.button--subtle.button--accent. A class that fuses two axes doesn’t exist.
Keyboard and screen readers
- Enter and Space both press a Button. The browser handles this, so don’t add key handlers.
- Tab reaches it, in reading order. Don’t change that with a positive
tabindex. - A toggle says its state through
aria-pressed, so a screen reader announces “pressed”. Keep the label the same in both states. - A disabled Button can’t be focused, so nobody using a keyboard can discover why it’s disabled. Say why near it.
Icons
Code
<button type="button" class="button button--strong button--accent">
<span>Get started</span>
<svg class="icon icon--dir" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#ArrowRight"/></svg>
</button>
<button type="button" class="button">
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Plus"/></svg>
<span>Add record</span>
</button>
<button type="button" class="button button--icon">
<span class="sr-only">Search site</span>
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Search"/></svg>
</button>
<button type="button" class="button button--plain button--icon button--round">
<span class="sr-only">More actions</span>
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#More"/></svg>
</button>
- Icon-only Buttons keep a text label in
.sr-only, so screen readers, translation and voice control (“click Search site”) all have a name. The icon isaria-hidden. .icon--dirmirrors an arrow in right-to-left text.--labeledkeeps the text when a container hides Button labels (--ui-labels: hidden).- An Avatar in a Button: a plain round icon Button holding a hidden Avatar.
Toggles and Choices
Code
<button type="button" class="button" aria-pressed="true"><span>Bold</span></button>
<label class="button">
<input type="checkbox" class="sr-only" />
<svg class="icon icon--off" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Close"/></svg>
<svg class="icon icon--on" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Check"/></svg>
<span>Notifications</span>
</label>
<div class="cluster" role="radiogroup" aria-label="Delivery">
<label class="button">
<input type="radio" name="delivery-demo" class="sr-only" checked />
<span>Standard</span>
<svg class="icon icon--on" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Check"/></svg>
</label>
<label class="button">
<input type="radio" name="delivery-demo" class="sr-only" />
<span>Express</span>
<svg class="icon icon--on" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Check"/></svg>
</label>
</div>
- A toggle Button takes
aria-pressed; its label stays the same as it changes (“Bold”, not “Bold on”). - A Checkbox or radio styled as a Button is a
<label class="button">around a visually hidden input. It needs no script, and the Input keeps its keyboard and screen-reader behaviour..icon--onand.icon--offshow with the state.
A Link that Looks Like a Button
Code
<a href="/start" class="button button--strong button--accent">
<span>Read the guide</span>
<svg class="icon icon--dir" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#ArrowRight"/></svg>
</a>
It goes somewhere, so it stays a Link: no role="button". Screen-reader users hear “link” and expect a new page; keyboard users open it with Enter (a Button also takes Space).
Do and Don’t
| Do | Don’t |
|---|---|
| Start the label with a verb: “Save changes”, “Delete project”. | Use “OK”, “Submit” or “Click here” when a verb would say what happens. |
| Use one strong accent Button per view, for the main action. | Make every Button strong; nothing stands out. |
| Say what a danger Button destroys, in its label. | Rely on red to say an action is destructive. |
| Give an icon-only Button a hidden text label. | Leave it to title, or to the icon alone. |
| Use a Link, styled as a Button if you like, to go to another page. | Put role="button" on a Link, or navigate from a <button> with script. |
| Explain near a disabled Button why it can’t be used yet. | Disable a submit Button without saying what’s missing. |
In Storybook
See also
- Button Group: A set of related Buttons laid out together, in a row or a column.
- Link and Block Link: A way to go somewhere else, in running text or as a row of its own.
- Menu: A list of actions in rows, usually opened from a Button in a Popover.
- Icon and Icon Box: A small glyph that helps people recognise something, on its own or in a frame.