Free pack

Button — .mv-button

Pure-CSS button on <button> or <a>: 6 variants, 4 sizes, loading state, group.

CategoryPrimitives
TypeCSS only (.mv-button)
Statusstable
Keywordsbutton, cta, group, loading

When to use

Avoid when

Install

node scripts/add.mjs button --out ./src/marvelous

AI agent with the Marvelous UI MCP server: install_components({ slugs: ["button"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Files copied (dependencies included): tokens/tokens.css, core/base.css, components/button/button.css.

Usage

Canonical markup — start from it and customize with attributes, data-* and CSS variables:

<div style="display:flex;flex-wrap:wrap;gap:.75rem;justify-content:center">
  <button class="mv-button">Primary</button>
  <button class="mv-button" data-variant="secondary">Secondary</button>
  <button class="mv-button" data-variant="outline">Outline</button>
  <button class="mv-button" data-variant="ghost">Ghost</button>
  <button class="mv-button" data-variant="destructive">Delete</button>
  <a class="mv-button" data-variant="link" href="#">Link</a>
</div>
<div style="display:flex;flex-wrap:wrap;gap:.75rem;align-items:center;justify-content:center">
  <button class="mv-button" data-size="sm">Small</button>
  <button class="mv-button" data-size="lg" data-shape="pill">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>
    Create
  </button>
  <button class="mv-button" data-variant="outline" data-size="icon" aria-label="Settings">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>
  </button>
  <button class="mv-button" aria-busy="true">Sending…</button>
  <button class="mv-button" disabled>Disabled</button>
  <div class="mv-button-group" role="group" aria-label="Alignment">
    <button class="mv-button" data-variant="outline">Left</button>
    <button class="mv-button" data-variant="outline">Center</button>
    <button class="mv-button" data-variant="outline">Right</button>
  </div>
</div>

API

Attributes

NameTypeDefaultDescription
data-variantsecondary | outline | ghost | destructive | link(primary)Visual style.
data-sizesm | lg | icon(md)Size; icon = square.
data-shapepill | roundFully rounded corners.
aria-busytrueShows a spinner and blocks clicks.

CSS classes

NameDescription
mv-buttonBase class, on <button> or <a>.
mv-button-groupContainer that joins several buttons together (add role="group").

CSS variables

NameDefaultDescription
--mv-button-radiusvar(--mv-radius-md)Corner radius.

Accessibility

Use a real <button> (or <a href> for navigation). Icon buttons must have an aria-label.