CSS Button Generator

Design accessible CSS buttons with hover, focus-visible and active states, then copy the CSS and HTML.

Runs in your browser

Button settings

Size and type

px
px
px

Colors and shape

Background
px
px
Shadow

Hover, focus and active

px
px
px
ms

Preview

Preview background

Hover, click and Tab to the button to test every state.

Presets

CSS

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 12px 24px;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
  color: #ffffff;
  background-color: #4f46e5;
  border: 0;
  border-radius: 8px;
  box-shadow: 0 4px 14px -4px rgba(79, 70, 229, 0.6);
  text-decoration: none;
  cursor: pointer;
  transition-property: background-color, color, box-shadow, transform;
  transition-duration: 200ms;
  transition-timing-function: ease;
}

.btn:hover {
  background-color: #4338ca;
  box-shadow: 0 10px 22px -6px rgba(79, 70, 229, 0.6);
  transform: translateY(-1px);
}

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

.btn:active {
  transform: translateY(0) scale(0.98);
  box-shadow: 0 4px 14px -4px rgba(79, 70, 229, 0.6);
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover,
  .btn:active {
    transform: none;
  }
}

HTML

<button type="button" class="btn">Get started</button>

Building good CSS buttons

A well-built button is more than a colored box. It needs comfortable padding and a readable font size, clear contrast between text and background, and distinct states: :hover for pointer users, :focus-visible for keyboard users and :active for the moment it is pressed. This generator writes all of them, plus a prefers-reduced-motion guard that switches off movement for people who have asked their system to reduce animation.

Use display: inline-flex with align-items: center so text and icons line up regardless of font metrics, and set line-height explicitly so the button height is predictable. Transition only the properties you change — background-color, color, box-shadow and transform — rather than transition: all, which can animate layout properties by accident and costs more to run.

Use a real <button> element for actions and an <a> link for navigation; the same class works on both. A <div> styled as a button is not focusable and is not announced as a button by screen readers.

How to use the CSS Button Generator

  1. Start from a preset — Primary, Outline, Pill, Ghost, 3D or Gradient — or edit the default button.
  2. Set the text, padding, font size, weight and family, then choose text and background colors, a border, radius and shadow.
  3. Configure the hover color, lift and shadow, the pressed effect and the keyboard focus ring.
  4. Hover, click and Tab to the preview button on a light, gray or dark background to test every state.
  5. Rename the class if needed, then copy or download the CSS and copy the HTML snippet.

Example

A minimal accessible primary button:

.btn {
  display: inline-flex;
  align-items: center;
  padding: 12px 24px;
  font: 600 16px/1.2 system-ui, sans-serif;
  color: #fff;
  background-color: #4f46e5;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 200ms ease;
}

.btn:hover {
  background-color: #4338ca;
}

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

Accessibility checklist

  • Text should reach a contrast ratio of at least 4.5:1 against the button background (3:1 for large, bold text). Check the hover state too.
  • Never remove the focus outline without a replacement. :focus-visible shows the ring to keyboard users without showing it on every mouse click.
  • Make touch targets at least 44×44 CSS pixels where possible — padding counts toward the target size.
  • Do not rely on color alone to show state; a lift, shadow or underline helps people with color-vision deficiencies.
  • Wrap movement such as hover lifts in a prefers-reduced-motion guard, as the generated CSS does.

Related tools

Fine-tune the elevation with the Box Shadow Generator, design richer backgrounds in the CSS Gradient Generator, or add a loading pulse with the CSS Animation Generator.

Frequently Asked Questions

What is the difference between :focus and :focus-visible?

:focus matches whenever the element has focus, including after a mouse click. :focus-visible only matches when the browser decides a visible indicator is needed — typically keyboard navigation — so you can show a strong ring without distracting mouse users. It is supported in all modern browsers.

How do I make a CSS button with a gradient hover effect?

Gradients cannot be transitioned directly. Make the background twice as wide with background-size: 200% auto and transition background-position on hover, which is what the Gradient preset generates.

Should I use a button or a link?

Use <button type="button"> (or type="submit" in forms) for actions that happen on the page and <a href> for navigation to another URL. Both can share the same CSS class.

Why use transform for the hover lift instead of margin or top?

transform does not affect layout, so neighbouring elements do not move and the browser can animate it on the compositor. Changing margin or top triggers layout on every frame.

Why is there a prefers-reduced-motion block?

Some users experience discomfort from movement and enable "reduce motion" in their operating system. The media query removes the lift and press transforms for them while keeping color changes.