Components
Button
Buttons allow users to take actions, and make choices, with a single tap.
Full support Supported since v125. Full support Supported since v128. Full support Supported since v18.
Variants
Change the button variant with the .outlined, .tonal, and .filled classes.
<div class="example-row"> <button class="button">Text</button> <button class="button" disabled>Disabled</button> <a class="button" href="#">Link</a></div><div class="example-row"> <button class="button outlined">Outlined</button> <button class="button outlined" disabled>Disabled</button> <a class="button outlined" href="#">Link</a></div><div class="example-row"> <button class="button tonal">Tonal</button> <button class="button tonal" disabled>Disabled</button> <a class="button tonal" href="#">Link</a></div><div class="example-row"> <button class="button filled">Filled</button> <button class="button filled" disabled>Disabled</button> <a class="button filled" href="#">Link</a></div>Colors
Add a .primary or .critical class to apply a brand
or destructive color. The default is a neutral gray.
<div class="example-row"> <button class="button primary">Primary</button> <button class="button primary outlined">Outlined</button> <button class="button primary tonal">Tonal</button> <button class="button primary filled">Filled</button></div><div class="example-row"> <button class="button critical">Critical</button> <button class="button critical outlined">Outlined</button> <button class="button critical tonal">Tonal</button> <button class="button critical filled">Filled</button></div>Buttons with icon and label
Include an icon alongside text by nesting an SVG element within the button.
<div class="example-row"> <button class="button"> Text <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
<button class="button outlined"> Outlined <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
<button class="button tonal"> Tonal <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
<button class="button filled"> Filled <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
</div><div class="example-row"> <button class="button"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> Text </button> <button class="button outlined"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> Outlined </button>
<button class="button tonal"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> Tonal </button>
<button class="button filled"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> Filled </button></div>Keyboard
Use the <kbd> element to provide keyboard hints within a
button.
<button class="button">Search <kbd>⌘K</kbd></button><button class="button outlined">Save <kbd>⌘S</kbd></button><button class="button tonal">Copy <kbd>⌘C</kbd></button><button class="button filled">Delete <kbd>⌘⌫</kbd></button>Icon-only
See Icon button documentation.
Sizes
Resize any button with the .small and .large
classes.
<div class="example-row"> <button class="button small">Small</button> <button class="button">Default</button> <button class="button large">Large</button></div>
<div class="example-row"> <button class="button filled small">Small</button> <button class="button filled">Default</button> <button class="button filled large">Large</button></div>
<div class="example-row"> <button class="button outlined small"> Small <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button> <button class="button outlined"> Default <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button> <button class="button outlined large"> Large <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button></div>Disabled
Add disabled styling with the disabled attribute or the .disabled class.
<div class="example-row"> <button class="button" disabled> Text </button>
<button class="button outlined" disabled> Outlined </button>
<button class="button tonal" disabled> Tonal </button>
<button class="button filled" disabled> Filled </button></div>
<div class="example-row"> <button class="button" disabled> Text <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
<button class="button outlined" disabled> Outlined <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
<button class="button tonal" disabled> Tonal <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button>
<button class="button filled" disabled> Filled <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path fill="currentColor" d="M11.75 3a.75.75 0 0 1 .743.648l.007.102l.001 7.25h7.253a.75.75 0 0 1 .102 1.493l-.102.007h-7.253l.002 7.25a.75.75 0 0 1-1.493.101l-.007-.102l-.002-7.249H3.752a.75.75 0 0 1-.102-1.493L3.752 11h7.25L11 3.75a.75.75 0 0 1 .75-.75"> </path> </svg> </button></div>File upload
Is it a button? Is it an input? You can find the docs for it here at least.
Anatomy
- Container
- Label text (optional)
- Icon (optional)
API
| Type | Modifiers | Default | Description |
|---|---|---|---|
| Sizes | .small, default, .large | - | The size of the element. |
| Variants | default, .outlined, .tonal, .filled | - | The variant to use. |
| Colors | .critical, .primary | - | Color modifiers. Default is a neutral gray. |
Browser support
Full support Supported since v125. Full support Supported since v128. Full support Supported since v18.
See also the full browser support guide.
Installation
@layer components.root { :where(.button) { --_color: light-dark(var(--color-16), var(--color-1)); --_color-contrast: light-dark(var(--color-1), var(--color-16)); --_color-tonal: var(--surface-tonal);
--_accent: var(--_color); --_accent-contrast: var(--_color-contrast); --_accent-tonal: var(--_color-tonal); --_accent-tonal-contrast: var(--_color);
--_default-hover-bg-color: light-dark(oklch(from var(--_accent) l 0.01 h / 10%), oklch(from var(--_accent) l 0.01 h / 20%)); --_default-active-bg-color: light-dark(oklch(from var(--_accent) l 0.06 h / 20%), oklch(from var(--_accent) l 0.06 h / 30%));
--_filled-hover-bg-color: light-dark(oklch(from var(--_accent) calc(l + 0.2) c h), oklch(from var(--_accent) calc(l - 0.1) c h)); --_filled-active-bg-color: light-dark(oklch(from var(--_accent) calc(l + 0.3) c h), oklch(from var(--_accent) calc(l - 0.15) c h)); --_outlined-active-bg-color: var(--_filled-active-bg-color);
--_bg-color: transparent; --_border-color: transparent; --_border-width: var(--border-size-1); --_font-size: var(--font-size-1); --_min-height: var(--button-size); --_border-radius: var(--button-border-radius, var(--radius-2)); --_text-color: var(--_accent);
-webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; align-items: center; background-color: var(--_bg-color); border: var(--_border-width) solid var(--_border-color); border-radius: var(--_border-radius); color: var(--_text-color); display: inline-flex; font-size: var(--_font-size); font-weight: 700; gap: var(--size-2); justify-content: center; min-block-size: var(--_min-height); padding-block: 0.5ex; padding-inline: 1.5ex; text-align: center; text-decoration: none; transition: background-color .1s ease, color .1s ease, border-color .1s ease, box-shadow .1s ease; user-select: none;
/* Colors — shared interaction model for critical and primary. Each color modifier below only swaps --_color; the tonal surface, contrast text, and hover/active strategy are identical. The .critical scope class in theme.css redirects --palette-source so --color-6 below becomes a tint of the active color. */ &.critical, &.primary { --_color-contrast: var(--gray-1); --_color-tonal: var(--color-6); --_accent-tonal-contrast: var(--text-primary-contrast);
--_default-hover-bg-color: oklch(from var(--_accent) l c h / 15%); --_default-active-bg-color: oklch(from var(--_accent) l c h / 25%);
--_filled-hover-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h); --_filled-active-bg-color: oklch(from var(--_accent) calc(l - 0.15) c h);
--_outlined-active-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h); }
&.critical { --_color: var(--critical); }
&.primary { --_color: var(--primary); }
/* Disabled */ &:where([disabled]) { --_text-color: color-mix(in oklch, var(--text-muted) 50%, var(--surface-default));
cursor: not-allowed; opacity: 0.64; }
/* Hover & Active */ &:where(:not([disabled])) { &:where(:not(:active):hover) { --_bg-color: var(--_default-hover-bg-color); }
&:where(:hover:active), &[aria-current="page"] { --_bg-color: var(--_default-active-bg-color); } }
/* Icons / Keyboard */ &:where(:has(svg), &.icon-only) { gap: 1ex;
svg { color: currentColor; max-block-size: 0.7lh; } }
/* Keyboard input */ :is(kbd) { background-color: oklch(from currentColor l c h / 10%); border: 0; color: oklch(from currentColor l c h / 80%); font-size: 0.8em; font-weight: 400; line-height: 1.2; }
/* Sizes — heights aliased from the shared --control-size scale. Override --button-size-* in a parent scope to resize an entire region. */ &.x-small { --_min-height: var(--button-size-x-small); --_font-size: var(--font-size-0); padding-block: 0; padding-inline: .5ex; }
&.small { --_min-height: var(--button-size-small); --_font-size: var(--font-size-05); padding-block: 0; padding-inline: .75ex; }
&.large { --_min-height: var(--button-size-large); padding-inline: 4ex; }
/* Variants */ &.outlined { --_bg-color: transparent; --_border-color: var(--_accent); --_text-color: var(--_accent);
&:where(:not([disabled])) { &:where(:not(:active):hover) { --_bg-color: var(--_accent); --_border-color: var(--_accent); --_text-color: var(--_accent-contrast); }
&:where(:active) { --_bg-color: var(--_outlined-active-bg-color); --_border-color: var(--_outlined-active-bg-color); --_text-color: var(--_accent-contrast); } } }
&.tonal { --_bg-color: var(--_accent-tonal); --_text-color: var(--_accent-tonal-contrast);
&:where(:not([disabled])) { &:where(:not(:active):hover) { --_bg-color: var(--_accent); --_text-color: var(--_accent-contrast); }
&:where(:active) { --_bg-color: var(--_outlined-active-bg-color); --_text-color: var(--_accent-contrast); } } }
&.filled { --_bg-color: var(--_accent); --_text-color: var(--_accent-contrast);
&:where(:not([disabled])) { &:where(:not(:active):hover) { --_bg-color: var(--_filled-hover-bg-color); }
&:where(:active) { --_bg-color: var(--_filled-active-bg-color); } } } }
/* file input */ :where(input[type="file"]) { align-self: flex-start; border: var(--border-size-1) solid var(--surface-filled); border-radius: var(--radius-2); box-shadow: var(--inner-shadow-4); color: var(--text-muted-contrast); cursor: initial; max-inline-size: 100%; padding: 0; }
:where(input[type="file"])::-webkit-file-upload-button, :where(input[type="file"])::file-selector-button { cursor: pointer; margin-inline-end: var(--size-relative-6); }}