Button

elements man style/components/button Read as markdown

A 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.

<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:

<input type="submit" value="Save"/>
<input type="submit" class="is-primary is-lg" value="Sign up"/>

The two modifiers they cannot take are is-loading and is-icon. Both need content inside the element, and an input is void, with no children and no ::before. Use a <button> when you need either.

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:

<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.

<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:

.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:

<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:

<div class="button-group">
  <button>Day</button>
  <button class="is-primary">Week</button>
  <button>Month</button>
</div>