Button
elements man style/components/button Read as markdownA bare <button> is a finished secondary button: bordered, correct height,
hover and active states, a focus ring. Add is- modifiers to change intent,
size, or state. Each modifier owns one axis, so they combine freely and order
never matters. This is button.css in @layer components.
Buttons<button>Cancel</button> <button class="is-primary is-lg is-block">Sign up</button>
Submit Inputs
input[type=submit], input[type=reset], and input[type=button] get the
same treatment with no class at all, and take the same modifiers. A submit
input is a button to whoever meets it, so it looks and behaves like one:
Submit inputs<input type="submit" value="Save"/> <input type="submit" class="is-primary is-lg" value="Sign up"/>
Use a <button> for is-loading and is-icon. Both draw content inside the
element, and an input is void, with no children and no ::before.
Coercion
To render a non-button element (typically an <a>) as a button, add .button.
It gets the identical treatment and takes all the same modifiers:
Coercion<a class="button is-primary" href="/install">Install</a>
Intents
| Class | Look |
|---|---|
(bare <button>) |
Bordered secondary |
is-primary |
Accent-filled call to action (monochrome until branded) |
is-ghost |
Borderless, quiet |
is-danger |
Red destructive fill |
is-primary fills with --accent and uses --accent-ink for its label, so it
takes your brand color automatically. is-danger fills with --danger and uses
white text deliberately (in dark mode --danger-ink is a light text tint, not a
fill foreground) and swaps in the danger focus ring.
Intents<button class="is-primary">Save</button> <button class="is-ghost">Skip</button> <button class="is-danger">Delete</button>
Sizes
| Class | Height |
|---|---|
is-sm |
32px |
| (default) | 40px |
is-lg |
48px |
is-hero |
56px |
Width, chrome, and state
| Class | Effect |
|---|---|
is-block |
Full width |
is-bare |
Strips all chrome: height, padding, border, background |
is-loading |
Progress cursor, muted, no pointer events |
is-disabled |
Disabled look (alongside the :disabled attribute) |
<button disabled> and aria-disabled="true" also get the disabled treatment.
Text alignment
A button centers its label, and text-align overrides that. This matters when
the button is wider than its text, which is what is-block, width: 100% or
flex: 1 in a row all do:
style.css.todo-title { flex: 1; text-align: start; }
A button holding elements rather than bare text, an icon beside a label, keeps
its parts centered as a group and ignores text-align.
Icon-only buttons
A button whose only child is a single <svg> goes bare automatically: square
padding, no border, a subtle hover fill. No class needed:
Icon-only button<button> <svg><!-- icon --></svg> </button>
Button group
.button-group joins adjacent buttons so they share borders. The group rounds
only its outer corners and collapses the seams between buttons:
Button group<div class="button-group"> <button>Day</button> <button class="is-primary">Week</button> <button>Month</button> </div>
Composing a button into a control
A bare <button> is a finished control with its own height, padding, border
and radius. To build one into a larger control, such as a stepper with a
button inside a bordered wrapper next to an <input>, hand those to the
wrapper:
style.css.stepper button { height: 100%; /* --button-height (2.75rem) otherwise wins even inside a */ min-height: 0; /* wrapper of the same height, and the hover fill paints */ /* over the wrapper's own border */ padding: 0; /* --button-padding-x survives `width`, pushing a single */ width: 2.75rem; /* glyph off centre under border-box */ } .stepper input { height: 100%; min-height: 0; padding: 0; border: none; border-radius: 0; background: none; }
When a composed control looks uneven, such as a hover fill that sits over the wrapper's border or a glyph off centre, set the bare element's height, padding, border or radius to fit the wrapper, as above. Here setting padding is part of composing the control.