State:
Advertisement
StateDefault
Radius10px
Size15px semibold
Pad20×12
⚠ 4.5:1

About this generator

Most CSS button generators give you a static button — set the colors, copy the code, ship it. Then the first developer who hovers over it discovers the hover state was an afterthought, the focus ring is missing, and the disabled style looks identical to enabled. This generator was built to fix exactly that gap.

All six interactive states — default, hover, active, focus, disabled, loading — live in one editor with tabs. Each state has its own complete style set; you can override only what changes from default and let the rest inherit, or pin a totally distinct treatment per state. The live preview lets you hover, click, and tab through the button so you can see every state actually fire, not just imagine what it would look like.

Three more differences worth calling out. Background-aware preview — pick the actual page background your button will sit on (white, dark, brand, gradient, mesh) so you can see whether the contrast holds. WCAG contrast scoring — live AA / AAA ratio for both text-on-button and button-on-page-background, so contrast-failing combos get flagged before you ship. Framework export — copy plain CSS, SCSS variables, Tailwind classes, React inline-style, or Vue scoped CSS. The output includes a proper :focus-visible ring and a prefers-reduced-motion guard automatically.

Permalink: every adjustment encodes into the URL hash, so you can bookmark a tuned button or send it to a teammate. No login, no watermark, no paywall. Free and MIT-licensed.

?

How to use

01
Edit the default state
Start on the Default tab. Set background, text color, radius, padding, font size, and shadow. The live preview updates as you drag any slider.
02
Switch to Hover / Active / Focus tabs
Each interactive state has its own complete style set. Override only what changes — leave the rest to inherit from Default. Most competitors skip this entirely; users get a button that "looks great until you hover."
03
Pick the right page background
Click a preset (White, Dark, Mesh) or pick a custom color. The button renders ON your actual page background — no more "looked great in the void" surprises.
04
Check WCAG contrast
The contrast panel shows text-on-button and button-on-page-background ratios. Aim for AA (4.5:1) minimum. AAA (7:1) for body text on critical CTAs.
05
Try a variation
Click any of the algorithmic remixes (Darker / Flat / Squared / Pill / Ghost) to instantly adopt that variant as your new default.
06
Export to your stack
Pick CSS, SCSS, Tailwind, React inline-style, or Vue scoped. Copy with one click. Output includes all interactive states, a focus ring, and a prefers-reduced-motion fallback.
</>

Common button snippets

All states
.btn {
  background: #6366f1;
  color: #fff;
  /* ...default styles */
}
.btn:hover { background: #5358e6; transform: translateY(-1px); }
.btn:active { background: #4a4fd6; transform: translateY(0); }
.btn:focus-visible { outline: 3px solid #a78bfa; outline-offset: 2px; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }
Reduced motion
@media (prefers-reduced-motion: reduce) {
  .btn { transition: none; }
}
Accessible markup
<!-- Correct: disabled = both visual + semantic -->
<button disabled aria-disabled="true">Saving…</button>

<!-- Correct: loading = visual spinner + busy semantic -->
<button aria-busy="true" disabled>
  <span class="spinner" aria-hidden="true"></span>
  Loading…
</button>
Tailwind
<button class="bg-indigo-500 hover:bg-indigo-600 active:bg-indigo-700
  text-white font-semibold px-5 py-3 rounded-lg
  transition-all duration-200
  focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2
  disabled:opacity-60 disabled:cursor-not-allowed
  motion-reduce:transition-none">
  Get started
</button>

Browser support

Every property the generator emits — including box-shadow, transitions, transform, focus-visible, prefers-reduced-motion — is supported in every evergreen browser. Safe to ship anywhere.

Chrome v1+
Safari v1+
Firefox v1+
Edge v12+

Pro tips

01
A button without hover state feels broken
Even a tiny color shift (5-10% darker) on hover signals to the user that the element is interactive. The 50ms-200ms transition between default and hover is the difference between "looks like a link" and "looks like a button."
02
Always add a focus indicator
WCAG 2.4.7 requires a visible focus state for keyboard users. The default browser ring is ugly but functional — don't set <code>outline: none</code> without replacing it with your own focus ring. The Focus tab generates an accessible <code>outline</code> by default.
03
Disabled buttons need visual AND semantic markers
A disabled button should look different (gray, reduced opacity) AND have the <code>disabled</code> HTML attribute. Screen readers announce "dimmed" or "unavailable" when the attribute is present, regardless of styling.
04
Don't pulse a primary CTA — it screams
Animated, pulsing buttons cross from "energetic" to "needy" fast. Subtle hover lift (translateY -1 to -2px) reads as polished. Continuous loops scream "click me!" and erode trust.
05
Respect prefers-reduced-motion
Vestibular-sensitive users disable motion in their OS. Always wrap hover transitions in a <code>@media (prefers-reduced-motion: reduce)</code> guard that removes the transition. The generator outputs this guard automatically.
06
Loading state needs pointer-events: none
A loading button must NOT accept clicks — otherwise users double-submit. Combine the visual spinner with <code>pointer-events: none</code> + <code>aria-busy="true"</code> on the element. The generator's Loading tab outputs this combination.

Search CodeFronts

Loading…