Skip to content

ExpressiveCSS

Browse documentation

Buttons

Material Design 3 common buttons, icon buttons, and FABs, from the HTML.

View as Markdown

Use a <button> for a filled common button, or an <a class="button"> for a link that looks the same. Put an <span class="material-symbols" aria-hidden="true"> icon before or after the label and wrap the label in its own <span>. The order of the two spans sets the placement. There is no icon-left or icon-right class. An icon-only button needs an aria-label, because the icon is hidden from assistive technology. Add circle for a round common button. Icon buttons are .icon-button.

A button has two independent axes: a style (filled, tonal, outlined, elevated, text) and a size (xsmall through xlarge). Any style combines with any size. That takes nine classes instead of twenty-five, because the size sets the geometry and the style sets the color.

Tokens follow the M3 button spec. The default is the small size: 40dp tall, a label-large label, fully round corners, a 20dp icon on an 8dp gap, and a symmetric 16dp inset. State layers are 8% on hover and 10% on focus or press. A disabled button uses on-surface at 38% on a 12% container.

A label that does not fit wraps between words, and the button grows taller. With enlarged text, 200% zoom or a narrow column, the label stays inside the button and the button stays inside its parent. The size's height is the minimum, so a label that fits looks the same. Keep the label in its own <span> so a single word longer than the parent can break as well. These stay on one line at a fixed height: circle buttons, FABs, extended FABs, Timepicker AM/PM controls, and buttons in button groups, split buttons, toolbars, top app bars, dialog and sheet headers, navigation bars and rails, tabs, pagination and snackbars. If a rule gives a button a smaller height, set min-height too, or set --md-comp-filled-button-container-height instead.

<button>Create</button>
<button>
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>
<button>
  <span>Send</span><span class="material-symbols" aria-hidden="true">send</span>
</button>
<button class="circle" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>

<a class="button" href="/docs">Link</a>

Filled

Filled is the default, high-emphasis style, for the main action on a page. The container is primary, the label is on-primary, and there is no elevation. It also has its own class, filled, so all five styles have a name. Adding it changes nothing.

Link

<button>Create</button>
<button class="filled">Create</button>
<button>
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>
<a class="button" href="/docs">Link</a>

Tonal

Add tonal for medium emphasis. The container is secondary-container and the label is on-secondary-container.

<button class="tonal">Create</button>
<button class="tonal">
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>

Outlined

Add outlined (or border) for medium emphasis with no fill. The outline is outline and the label is primary.

<button class="outlined">Create</button>

Elevated

Add elevated for medium emphasis with a shadow. The container is surface and the label is primary, with elevation 1 at rest and 2 on hover. Use it sparingly so the page does not fill with shadows.

<button class="elevated">Create</button>

Text

Add text for low emphasis. It has no container, and the label is primary. Use text buttons inside cards and dialogs so they do not stack shadows.

<button class="text">Create</button>

Icon buttons

.icon-button is its own component. circle on a common button is the older round common-button form and still works. It follows the size scale, 40dp by default. The variant helpers still apply. The default is filled, text gives the standard (transparent) icon button, and tonal and outlined match the common-button colors.

<button class="circle" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
<button class="circle tonal" aria-label="Add">…</button>
<button class="circle outlined" aria-label="Add">…</button>
<button class="circle text" aria-label="Add">…</button>

Floating

For a FAB, use circle extra or circle large. It is 56dp with 16dp corners, primary-container and elevation 3. extra circle medium is the 80dp medium one (20dp corners, 26dp icon), and extra circle large is the 96dp large one (28dp corners, 36dp icon). The large size needs the extra, because circle large on its own is the alias for the default 56dp FAB.

Use extend small for the extended FAB, an icon and a label at 56dp, with 16dp corners and 8dp between the two. It takes the three explicit sizes. extend small is 56dp on a symmetric 16dp inset, extend medium is 80dp (20dp corners, 28dp icon) and extend large is 96dp (28dp corners, 36dp icon). Each uses the label role Material gives it. Its container colour is also a role. Adding secondary-container or tertiary-container recolours the label and the state layers to match. See the FAB page for the whole axis.

<button class="circle extra" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
<button class="circle extra medium" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
<button class="circle extra large" aria-label="Add">
  <span class="material-symbols" aria-hidden="true">add</span>
</button>
<button class="extend small">
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>
<button class="extend medium">
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>
<button class="extend large secondary-container">
  <span class="material-symbols" aria-hidden="true">add</span><span>Create</span>
</button>

Sizes

Buttons come in five sizes. small is the default at 40dp with a 20dp icon, so it needs no class. The rest are xsmall (32dp, 20dp icon), medium (56dp, 24dp, title-medium label), large (96dp, 32dp, headline-small) and xlarge (136dp, 40dp, headline-large). The inset and the icon gap grow with the size, and an outlined button's border thickens with it: 1dp up to medium, 2dp at large and 3dp at extra large. circle follows the same size scale. A round common button takes both the box and the icon size of its step, 40dp with a 20dp icon by default and 136dp with a 40dp icon at xlarge. Only circle extra and circle large leave this scale, because they are FAB sizes with a scale of their own. For the icon button's numbers, 40dp with a 24dp icon, use .icon-button.

<button class="xsmall">Extra small</button>
<button>Small</button>
<button class="medium">Medium</button>
<button class="large">Large</button>
<button class="xlarge">Extra large</button>

Write the two axes side by side. There is no per-combination class, so any style works with any size.

<button class="tonal medium">Tonal medium</button>
<button class="outlined xsmall">Outlined extra small</button>
<button class="text medium">Text medium</button>

For a form submit, use a real <button type="submit"> rather than an input.

<button type="submit">
  <span>Submit</span><span class="material-symbols" aria-hidden="true">send</span>
</button>

Shape and toggles

Buttons are round. Add square for the squared corner of the size: 12dp up to small, 16dp at medium and 28dp at large and extra large. When pressed, every common button morphs its corners to the pressed shape of its size (8dp up to small, 12dp at medium and 16dp beyond) and springs back on release.

<button>Round</button>
<button class="square">Square</button>
<button class="tonal square medium">Square medium</button>

Add aria-pressed to make a button a toggle. When selected, a round button goes square and a square one goes round, so the cue does not rely on colour alone. The colours change too: filled from surface-container to primary, tonal from secondary-container to secondary, outlined to inverse-surface without its outline, and elevated to primary. Text buttons do not toggle. Switch aria-pressed in your click handler. For a set of toggles that share a row, use a button group.

<button type="button" aria-pressed="false">Filled</button>
<button type="button" aria-pressed="true">Filled</button>
<button type="button" class="tonal" aria-pressed="true">Tonal</button>
<button type="button" class="outlined" aria-pressed="true">Outlined</button>
<button type="button" class="elevated square" aria-pressed="true">Elevated square</button>

Disabled

Use the disabled attribute, or the disabled class on a link. It applies to every variant.

<button disabled>Filled</button>
<button class="tonal" disabled>Tonal</button>
<a class="button disabled">Link</a>

No matching pages

  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.

    Default source: Mist Iris.

    ExpressiveCSS presets: Lagoon, Harbor, Breeze, Cobalt, Iris.

    Bold

    Soft

    Mist

    Glow