CSS Button Generator

Design a button visually and copy production-ready code. Pick from 16 styles, including gradient, glass, neumorphic, 3D press and neon, add one of 35+ hover and click effects, and tune every state from hover to loading. Live accessibility checks keep contrast, focus rings and target size in line with WCAG 2.2, and you can export CSS, CSS variables, SCSS, Tailwind, React, HTML or a Shopify snippet.

Preset gallery
Hover
Focus
Pressed
Disabled
Loading

Accessibility checks

  • Pass Text contrast 6.29:1 meets WCAG 2.2 AA (needs 4.5:1).
  • Pass A visible 3px focus ring is included (6.29:1 against the background).
  • Pass Animations and transitions switch off under prefers-reduced-motion.
  • Pass Target height 44px meets the 44px touch recommendation.

Export code

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 24px;
  min-height: 44px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  color: #FFFFFF;
  background: #4F46E5;
  border: 0;
  border-radius: 10px;
  box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.12);
  cursor: pointer;
  text-decoration: none;
  user-select: none;
  transition: transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1), box-shadow 180ms cubic-bezier(0.2, 0.8, 0.2, 1), background-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), background-position 180ms cubic-bezier(0.2, 0.8, 0.2, 1), color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), border-color 180ms cubic-bezier(0.2, 0.8, 0.2, 1), filter 180ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.btn:hover:not(:disabled) {
  filter: brightness(1.06);
  transform: translateY(-1px);
  box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0 10px 24px -6px rgba(79, 70, 229, 0.45);
}

.btn:focus-visible {
  outline: 3px solid #4F46E5;
  outline-offset: 2px;
}

.btn:active:not(:disabled) {
  filter: brightness(0.96);
  transform: scale(0.98);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  filter: none;
}

.btn[aria-busy="true"] {
  cursor: progress;
  opacity: 0.85;
}

@media (prefers-reduced-motion: reduce) {
  .btn,
  .btn::before,
  .btn::after,
  .btn * {
    transition: none;
    animation: none;
  }
}
Import CSS (copy from a site)

Paste CSS from your site or browser dev tools: a rule or just declarations. Supported properties are loaded into the controls; everything else is listed. You can undo the import.

Favourites on this device (0)

No favourites yet.

Style & content
Icon position
Size & typography
Shape & border
Colors & background
Shadows
States
Motion & effects

How to use the CSS button generator

  1. Start from a preset in the gallery or keep the default. Filter by style (minimal, glass, neon, 3D and more) and select Customize to load one into the controls.
  2. Choose a variant, button text, icon and size scale under Style & content and Size & typography.
  3. Shape it with corner radius (all corners or each one), border width, style and color.
  4. Color it with a solid fill or a linear, radial, conic or animated gradient, and add up to four shadow layers.
  5. Design the states: how the button reacts on hover and press, its focus ring, and how it looks when disabled. The state row under the preview shows them all at once.
  6. Add motion with one of 35+ effects and set the duration and easing. Choose Custom curve to drag the cubic-bezier handles or nudge them with the arrow keys.
  7. Check accessibility, then copy or download the code in the format you need. Use Undo and Redo (Ctrl+Z / Ctrl+Shift+Z) freely, and Save as A to compare two versions side by side.

How it works: what the CSS does

Each design becomes one class, .btn, plus state selectors:

  • :hover:not(:disabled) changes the button only when it can actually be pressed.
  • :focus-visible draws an outline ring for keyboard users. The ring uses outline with an outline-offset, so it never changes the layout.
  • :active:not(:disabled) gives the press feedback, usually a slight scale or a downward move.
  • :disabled and [aria-disabled="true"] reduce opacity and show a not-allowed cursor. [aria-busy="true"] marks a loading button.

Effects that need an extra layer use ::before or ::after pseudo-elements, such as the shine sweep, the fills and the ripple. The button then gets position: relative and, where needed, overflow: hidden, and its content is lifted above the effect layer so the label stays readable. Animated effects add @keyframes named after the class to avoid clashes.

Every export ends with a prefers-reduced-motion block that turns transitions and animations off for people who ask their device to reduce motion.

Browser support and performance

Everything here works in current versions of Chrome, Edge, Firefox and Safari. backdrop-filter (glass) is supported in all of them, and the export includes the -webkit- prefix for older Safari. The generated transitions animate only transform, opacity, filter, box-shadow and colors. Transform and opacity are composited by the GPU and stay smooth; large animated shadows and filters cost more, so keep them for buttons rather than whole sections.

Worked examples

Example 1: a primary call to action

Load Solid · Indigo, keep the Lift effect and set the size to LG. The button gets a 3:1-plus focus ring, a raised hover shadow and a 0.98 press scale. The contrast check shows white on indigo at about 6.3:1, comfortably above the 4.5:1 AA requirement.

Example 2: a glass button over a photo

Load Glass · Sky, switch the preview background to Image and add the Spotlight effect. The background is translucent with backdrop-filter: blur(12px). Watch the contrast check: translucent buttons depend on what’s behind them, so test them on the real background.

Example 3: a Shopify “Add to cart” button

Load 3D press · Emerald, set the text to “Add to cart” and choose the cart icon. The Shopify Liquid tab produces a snippet you can save as snippets/atx-button.liquid and render with a label and URL. The 3D press uses a hard bottom shadow that collapses when pressed.

Common mistakes

  • Removing the focus outline. outline: none without a replacement makes the button unusable with a keyboard. The generator always keeps a ring.
  • Low-contrast hover states. A lighter hover color can drop below 4.5:1. Preview the hover state and check the ratio.
  • Tiny touch targets. Icon-only buttons in particular often end up under 44px. Keep the minimum height at 44px for touch.
  • Animating layout properties. Animating width, height or padding causes layout work on every frame. Use transform and opacity instead.
  • Using a div as a button. Always use <button> (or <a> for navigation) so keyboard and screen-reader support come for free.

Import CSS from your site

Already have a style you like? Open Import CSS (copy from a site), paste a rule or just its declarations from your stylesheet or your browser’s developer tools, and press Import into the controls. This tool reads background (colors and gradients), color, border, border-radius, padding, font size, weight, family and letter-spacing, text-transform, height, width, box-shadow and transition duration. Everything else, and rules for states such as :hover or media queries, is listed as skipped, and the import can be undone in one step.

Frequently asked questions

Is the generated CSS accessible?

Every export keeps a visible focus-visible ring, turns animations off for people who prefer reduced motion, and styles the disabled and busy states. The live checks also show text contrast against WCAG 2.2 AA and whether the button meets the 24px minimum and the 44px touch recommendation.

Why does the code use :focus-visible instead of :focus?

:focus-visible shows the ring when someone navigates with a keyboard but not after a mouse click, which is what most designers want. It's supported in all current browsers, and the ring is never removed, so keyboard users can always see where they are.

Can I use the button with Tailwind CSS?

Yes. The Tailwind tab converts the design into utility classes, using arbitrary values and properties where Tailwind has no built-in class. Effects that need pseudo-elements or keyframes, such as the shine sweep, can't be written as utilities; the export lists them so you can add the CSS export under @layer components.

Do hover effects work on phones?

Touch screens have no true hover, so hover effects appear briefly on tap at most. Click effects such as ripple, micro bounce and squish respond to taps. Make sure the button looks complete without its hover effect.

Why does the CSS list specific transition properties instead of "all"?

Transitioning "all" makes the browser watch every property, including expensive ones like width and padding, and can animate things you didn't intend. Listing transform, box-shadow, colors, filter and opacity keeps animations smooth and predictable.

How do I share a design with a teammate?

Copy share link stores the whole design in the URL, so opening it restores every setting. Nothing is uploaded; the design lives entirely in the link. You can also save favourites on your device.

Can I make a set of buttons for a design system?

The Button system tab exports primary, secondary, tertiary and danger buttons in small, medium and large sizes, driven by CSS custom properties so you can retheme them in one place.

Sources