button
Interactive control for form submission, dialogs, and user actions. Vanilla Breeze styles buttons with inline-flex layout, design tokens, and variant classes for visual hierarchy.
When to Use
- Submitting or resetting a form
- Triggering actions on the current page (opening dialogs, toggling states)
- Any interactive element that performs an action rather than navigation
When NOT to Use
Do not use <button> for navigation. Use <a> instead. If you need a link that looks like a button, apply class="button" to an anchor element.
Style Variants
Visual variants communicate hierarchy and importance. Use primary for the main action, secondary for supporting actions, and ghost for tertiary or de-emphasized actions.
| Class | Appearance | Use Case |
|---|---|---|
| (default / primary) | Solid --color-interactive background, white text |
Primary action. Use sparingly, typically once per section |
.secondary |
Transparent with colored border and text | Supporting action that pairs with primary |
.ghost |
No background or border, text-only | Tertiary or de-emphasized actions |
<button type="button">Primary</button><button type="button" class="secondary">Secondary</button><button type="button" class="ghost">Ghost</button>
Sizes
Size variations accommodate different contexts, from compact inline actions to full-width form submissions.
| Class | Padding | Font Size | Use Case |
|---|---|---|---|
.small |
xs / s | sm | Compact interfaces, inline actions |
| (default) | s / m | inherit | Standard actions |
.large |
m / l | lg | CTAs, hero sections |
.full-width |
(inherits) | (inherits) | Full-width buttons, mobile form submit |
<button type="button" class="small">Small</button><button type="button">Default</button><button type="button" class="large">Large</button><button type="button" class="full-width">Full Width</button>
Button Types
The type attribute determines the button's behavior within a form.
| Type | Behavior | When to Use |
|---|---|---|
button |
No default behavior | JavaScript actions, dialogs, toggles |
submit |
Submits the parent form (default in forms) | Form submission |
reset |
Resets form fields to initial values | Clear form data |
<!-- Default button (for JS actions) --><button type="button">Click Me</button> <!-- Form submission --><button type="submit">Submit</button> <!-- Form reset --><button type="reset">Reset</button>
Buttons with Icons
Buttons can include icons using the icon-wc component. The button's inline-flex layout with gap: var(--size-xs) automatically handles alignment.
For icon-only buttons, always include aria-label to provide an accessible name.
<button type="button"> <icon-wc name="plus"></icon-wc> Add Item</button> <button type="button" class="secondary"> <icon-wc name="download"></icon-wc> Export</button> <!-- Icon-only button — always include aria-label --><button type="button" aria-label="Close dialog"> <icon-wc name="x"></icon-wc></button>
Dialog Triggering
Buttons can open and close dialogs declaratively using the Invokers API. Point commandfor at the dialog's id and set command to show-modal or close. No JavaScript required.
<!-- Open a dialog with the Invokers API --><button type="button" commandfor="my-dialog" command="show-modal"> Open Dialog</button> <dialog id="my-dialog"> <header> <h2>Dialog Title</h2> <button type="button" class="ghost" commandfor="my-dialog" command="close" aria-label="Close"> <icon-wc name="x"></icon-wc> </button> </header> <article> <p>Dialog content here.</p> </article> <footer class="actions end"> <button type="button" class="secondary" commandfor="my-dialog" command="close">Cancel</button> <button type="button" commandfor="my-dialog" command="close">OK</button> </footer></dialog>
Buttons in Forms
Buttons work seamlessly within form elements. Group actions in a <footer class="actions end"> to right-align them. For enhanced form fields, see the form-field custom element.
<form class="stacked"> <form-field> <label for="email">Email</label> <input type="email" id="email" /> </form-field> <footer class="actions end"> <button type="reset" class="ghost">Reset</button> <button type="button" class="secondary">Cancel</button> <button type="submit">Subscribe</button> </footer></form>
Button-Styled Links
Need a link that looks like a button? Use class="button" on an <a> element. All variants and sizes apply: .secondary, .ghost, .small, .large, .full-width.
<a href="/signup" class="button">Sign Up</a><a href="/pricing" class="button secondary">View Pricing</a><a href="/docs" class="button ghost">Learn More</a>
See the <a> documentation for full examples and guidelines on when to use a link vs a button.
Accessibility
- Always include text: Buttons should have visible text. For icon-only buttons, add
aria-label - Use native buttons: Avoid
<div onclick>patterns. Native buttons are keyboard accessible by default - Visible focus: The
:focus-visibleoutline is essential for keyboard navigation. Do not remove it - Disabled state: Disabled buttons are not focusable. Consider keeping buttons enabled with validation messages instead
- Minimum touch target: Buttons enforce a minimum size of
var(--size-touch-min)(44x44px) for touch accessibility
CSS Reference
button, .button { display: inline-flex; align-items: center; justify-content: center; gap: var(--size-xs); padding-block: var(--size-s); padding-inline: var(--size-m); min-block-size: var(--size-touch-min); min-inline-size: var(--size-touch-min); background: var(--color-interactive); color: white; border: none; border-radius: var(--radius-m); font: inherit; font-weight: 500; cursor: pointer; transition: background var(--duration-fast) var(--ease-default);} button:hover { background: var(--color-interactive-hover);} button:focus-visible { outline: var(--border-width-medium) solid var(--color-interactive); outline-offset: var(--border-width-medium);} button:disabled { opacity: 0.5; cursor: not-allowed;} /* --- Variants --- */ button.secondary { background: transparent; color: var(--color-interactive); border: var(--border-width-thin) solid currentColor;} button.ghost { background: transparent; color: var(--color-text);} /* --- Sizes --- */ button.small { padding-block: var(--size-xs); padding-inline: var(--size-s); font-size: var(--font-size-sm);} button.large { padding-block: var(--size-m); padding-inline: var(--size-l); font-size: var(--font-size-lg);} button.full-width { inline-size: 100%;}
Related
- a - For navigation; use
class="button"for button-styled links - form - Container for form controls including buttons
- dialog - Dialogs triggered by buttons via the Invokers API
- menu - Menu of actions triggered by buttons
- icon-wc - Icon component for buttons with icons
- form-field - Enhanced form field wrapper