Skip to button documentation
Boobstrap Docs
Components

Buttons

Use buttons to trigger actions, navigate to a destination, group related controls, or communicate asynchronous work. Boobstrap supplies the visual system in CSS and adds behavior only where state management is required.

CSS required JavaScript optional 21 public classes
Start here

Overview

Every button begins with .bs-btn and one hierarchy modifier. Use a native <button> for an action and an <a href> when activating the control navigates somewhere.

Read the docs
HTML · Semantic elements
<button class="bs-btn bs-btn-primary" type="button">Save changes</button>

<a class="bs-btn bs-btn-secondary" href="/docs">Read the docs</a>

Links styled as buttons

Add .bs-btn and any visual modifier to an anchor with a real href. It receives the same sizing, focus treatment, spacing, and variants as a button while preserving native link behavior such as opening in a new tab or copying the destination.

Choose by behavior, not appearance.

Do not use a link as a button just to get button styling. The element determines keyboard, form, and navigation behavior; the classes determine presentation.

Hierarchy

Variants

Choose one emphasis level based on the action’s importance within its current region. Most screens need one primary action, a few supporting actions, and quiet ghost actions.

HTML · Variants
<button class="bs-btn bs-btn-primary" type="button">Primary</button>
<button class="bs-btn bs-btn-secondary" type="button">Secondary</button>
<button class="bs-btn bs-btn-ghost" type="button">Ghost</button>
Primary

Commit the main action

Use once per focused region for actions such as Save, Continue, or Create.

Secondary

Offer an alternative

Use for supporting actions that should remain easy to discover.

Ghost

Keep it quiet

Use for tertiary actions, compact navigation, and low-risk dismissal.

Scale & layout

Sizes and width

The default size is appropriate for most interfaces. Use small buttons in dense toolbars, large buttons for a prominent call to action, and block buttons when the container should define the width.

HTML · Sizes and block
<button class="bs-btn bs-btn-primary bs-btn-sm" type="button">Small</button>
<button class="bs-btn bs-btn-primary" type="button">Default</button>
<button class="bs-btn bs-btn-primary bs-btn-lg" type="button">Large</button>

<button class="bs-btn bs-btn-secondary bs-btn-block" type="button">Full-width action</button>
Touch targets: the default button is 2.75rem high and the large button is 3.35rem high. Be careful when using small buttons for primary mobile actions or controls that need generous touch space.
Visual cues

Icons

Place an inline SVG before or after the label; .bs-btn handles spacing. Add .bs-btn-icon only when the icon is the complete visible label.

HTML · Inline SVG
<button class="bs-btn bs-btn-primary" type="button">
  <svg class="bs-icon" viewBox="0 0 24 24" aria-hidden="true">
    <path d="M12 5v14M5 12h14" />
  </svg>
  Create
</button>

<button class="bs-btn bs-btn-secondary bs-btn-icon" type="button"
  aria-label="Add to favorites">
  <svg class="bs-icon" viewBox="0 0 24 24" aria-hidden="true">
    <path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.7l-1.1-1.1a5.5 5.5 0 0 0-7.8 7.8L12 21l8.8-8.6a5.5 5.5 0 0 0 0-7.8Z" />
  </svg>
</button>
Icons stay optional.

Boobstrap does not ship an icon library. Use dependency-free SVG markup, Lucide, or your preferred icon set. Decorative icons need aria-hidden="true"; icon-only buttons need an accessible name.

Interaction feedback

States

Hover, active, and focus-visible feedback are automatic. Use semantic attributes for persistent pressed and disabled states so assistive technology receives the same information as sighted users.

Default
Pressed
Active style
Disabled
HTML · Persistent states
<button class="bs-btn bs-btn-secondary" type="button" aria-pressed="true">Pinned</button>

<button class="bs-btn bs-btn-primary bs-btn-active" type="button">Current</button>

<button class="bs-btn bs-btn-primary" type="button" disabled>Unavailable</button>
Disabled links need application logic. If a link must appear unavailable, remove its href, add aria-disabled="true" and .bs-btn-disabled, and prevent activation in your application. Prefer a real button whenever the control performs an action.
Related controls

Button groups and toolbars

A group joins adjacent related buttons into one visual control. A toolbar lays out one or more groups and wraps them when space is constrained.

HTML · Labeled toolbar
<div class="bs-btn-toolbar" role="toolbar" aria-label="Editor controls">
  <div class="bs-btn-group bs-btn-group-sm" role="group" aria-label="Text alignment">
    <button class="bs-btn bs-btn-secondary" type="button" aria-pressed="true">Left</button>
    <button class="bs-btn bs-btn-secondary" type="button" aria-pressed="false">Center</button>
    <button class="bs-btn bs-btn-secondary" type="button" aria-pressed="false">Right</button>
  </div>
</div>

Structure

Keep each .bs-btn-group focused on one family of actions. Place multiple groups inside .bs-btn-toolbar.

Sizing

Apply .bs-btn-group-sm or .bs-btn-group-lg to the group so every child shares one size.

Accessibility

Add role="group" or role="toolbar" and an accessible label that describes the controls as a set.

Compound actions

Split dropdown buttons

Keep the main action on the first button and attach a compact trigger for related alternatives. Split dropdown behavior is available through Boobstrap JS, Alpine, or React.

HTML · Boobstrap JS
<div class="bs-dropdown bs-btn-group" data-bs-dropdown>
  <button class="bs-btn bs-btn-primary" type="button">Save changes</button>
  <button class="bs-btn bs-btn-primary bs-btn-split bs-btn-caret"
    id="save-toggle" type="button" data-bs-toggle="dropdown"
    aria-controls="save-menu" aria-label="More save options"></button>
  <div class="bs-dropdown-menu bs-dropdown-menu-end" id="save-menu"
    role="menu" aria-labelledby="save-toggle" data-bs-dropdown-menu hidden>
    <button class="bs-dropdown-item" type="button" role="menuitem">Save and publish</button>
    <button class="bs-dropdown-item" type="button" role="menuitem">Save as draft</button>
  </div>
</div>
Keyboard behavior: Arrow Down opens the menu and focuses its first enabled item. Arrow keys, Home, and End move through items; Escape closes the menu and restores focus to the trigger.
Asynchronous actions

Loading buttons

The loading controller prevents repeat activation, applies busy and disabled state, replaces the accessible name, and restores the button after your application calls stop().

HTML · Boobstrap JS
<button class="bs-btn bs-btn-primary" type="button"
  data-bs-button data-bs-loading data-bs-loading-label="Saving changes">
  <span class="bs-btn-label">Save changes</span>
  <span class="bs-spinner bs-btn-spinner" aria-hidden="true"></span>
</button>

<script type="module">
  import { Button } from "@boobstrap/boobstrap/js/button";
  const element = document.querySelector("[data-bs-button]");
  const save = Button.getOrCreateInstance(element);
  element.addEventListener("click", async () => {
    await persistChanges();
    save.stop();
  });
</script>
Your application owns completion.

Boobstrap starts and presents the loading state. Always call stop() in a finally path so failures and cancellations restore the control.

Reference

Class and JavaScript API

Button modifiers compose across hierarchy, size, shape, layout, and state. JavaScript is required only for managed loading state and dropdown behavior.

CSS classes

ClassPurposeNotes
.bs-btnBase alignment, spacing, typography, focus, and interaction styles.Required on every button.
.bs-btn-primaryHigh-emphasis gradient action.Prefer one per focused region.
.bs-btn-secondaryBordered supporting action.For alternatives and secondary actions.
.bs-btn-ghostTransparent, low-emphasis action.For tertiary actions and quiet navigation.
.bs-btn-smCompact button sizing.2.25rem minimum height.
.bs-btn-lgLarge button sizing.3.35rem minimum height.
.bs-btn-iconSquare, size-aware icon-only button.Requires an accessible name.
.bs-btn-blockStretches to the container width.Useful in narrow forms and panels.
.bs-btn-toolbarWraps and spaces groups.Add role="toolbar" and a label.
.bs-btn-groupJoins adjacent buttons.Add role="group" and a label.
.bs-btn-group-smSizes all group children small.Apply to the group.
.bs-btn-group-lgSizes all group children large.Apply to the group.
.bs-btn-splitCompact attached trigger width.Combine with a group and dropdown.
.bs-btn-caretDraws a CSS-only disclosure caret.No icon dependency required.
.bs-btn-activePersistent active appearance.Use aria-pressed for toggles.
.bs-btn-disabledDisabled appearance for non-button elements.Does not prevent events by itself.
.bs-btn-labelPreserves the label width and accessible text during loading.Wrap the visible loading-button label.
.bs-spinnerCurrent-color spinner.Use size modifiers as needed.
.bs-spinner-sm / .bs-spinner-lgCompact or large spinner sizing.Can be used inside or outside buttons.
.bs-btn-spinnerCenters a spinner during button loading state.Pair with .bs-spinner.

Button controller

JavaScript · Component import
import { Button } from "@boobstrap/boobstrap/js/button";

const save = Button.getOrCreateInstance(document.querySelector("[data-bs-button]"));
save.start();
save.stop();
save.toggle();
save.destroy();
Method or eventContract
start(options?)Enters loading state and returns true when the transition completes.
stop(options?)Restores the original attributes and returns true when the transition completes.
toggle(options?)Starts or stops based on the current state.
destroy()Removes listeners, restores loading state, and releases the instance.
bs:button:start / bs:button:stopCancelable before-events. Calling preventDefault() prevents the transition.
bs:button:started / bs:button:stoppedBubbling events emitted after a completed transition.
Ship responsibly

Accessibility

Boobstrap supplies focus-visible treatment and state styling. Your markup and application logic still own meaning, names, state, and correct keyboard behavior.

  • Use <button type="button"> for actions and <a href> for navigation.
  • Set an explicit button type; the default inside a form is submit.
  • Give icon-only buttons and split triggers a concise accessible name with aria-label or visible text.
  • Mark decorative SVG icons aria-hidden="true" so they do not duplicate the label.
  • Use aria-pressed="true|false" for toggle buttons and keep their accessible label stable.
  • Prefer the native disabled attribute. Remember that aria-disabled communicates state but does not block activation.
  • Label button groups and toolbars so their relationship is announced to assistive technology.
  • Keep loading labels specific—“Saving changes” is more useful than “Loading”—and restore the control on every completion path.
Do not remove focus indication.

The built-in focus ring is intentional. If your theme overrides it, provide an equally visible replacement in both light and dark themes.