CSS button generator

Design a button — size, colours or a gradient, border, corners, shadow and a hover effect — and see whether its text is readable, with the WCAG contrast ratio checked as you go. Copy the CSS and HTML, or Tailwind CSS classes.

Backdrop
Text contrast 6.28:1 AA pass
On hover 7.85:1 AA pass

Normal text: AA needs 4.5:1 (3:1 from 24px, or 19px bold).

Size and shape
Colours
Shadow
Hover
CSS
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 24px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  font-size: 16px;
  font-weight: 600;
  line-height: 1.25;
  color: #ffffff;
  background: #4f46e5;
  border: none;
  border-radius: 8px;
  box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  cursor: pointer;
  text-decoration: none;
  transition: background-color 150ms ease, color 150ms ease, transform 150ms ease;
}
.btn:hover {
  background: #433cc3;
}
.btn:focus-visible {
  outline: 2px solid #4f46e5;
  outline-offset: 2px;
}
HTML
<button type="button" class="btn">Get started</button>
Tailwind CSS
<button type="button" class="inline-flex items-center justify-center px-6 py-3 font-sans text-base font-semibold leading-tight text-white bg-[#4f46e5] border-0 rounded-lg shadow-sm cursor-pointer no-underline transition duration-150 hover:bg-[#433cc3] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#4f46e5]">Get started</button>

What the CSS does

Contrast: can people read the label?

WCAG 2 compares the relative luminance of the text and the background. Level AA asks for at least 4.5:1 for normal text, and 3:1 for large text — 18pt (24px) and up, or 14pt (about 18.7px) and up when bold. The tool checks both the normal and the hover state, because a darker or lighter hover colour can fail where the normal one passed. On a gradient it uses the stop that gives the worst contrast, since the label may sit over either end. A transparent button is checked against the backdrop you picked above. Ratios are cut, never rounded up: 4.499 shows as 4.49 and fails.

How we test it

For 320 different buttons — every preset plus random settings — the CSS is pasted exactly as you would copy it into Chrome 156, and the browser's computed padding, font, line height, colours, background, borders, corners, shadow and transition must equal the settings. The :hover and :focus-visible states are forced through Chrome's DevTools protocol and checked too: hover colours, the lift in pixels and the focus outline (15,360 values in all). The Tailwind classes are compiled with Tailwind CSS 4.3.3 and must compute the same in all three states. The 640 contrast ratios are recomputed from the colours Chrome actually painted with an independent library (culori) and must agree. Each check is also run against deliberately broken versions of the generator (7 kinds, such as padding off by 1px, gradient stops swapped or contrast taken from the best stop), and each one must catch them.

Questions

Should I use a button or a link?

Use <button> for an action on the page (submit, open, save) and <a href> for going somewhere else. The same .btn class works on both — the CSS sets text-decoration: none and cursor: pointer so a link looks and feels like the button.

How big should a button be?

Big enough to tap: WCAG 2.2 asks for at least 24×24px, and Apple and Google recommend 44 or 48px for touch. With a 16px font and a 1.25 line height the label is 20px tall, so 12px of padding top and bottom gives a 44px button.

Why does the hover lift use transform?

transform moves the button without changing the layout around it, so nothing else on the page jumps, and the browser can animate it cheaply. Tailwind's -translate-y-* classes do the same with the translate property.

Which Tailwind classes does it give?

Tailwind CSS v4. Values on Tailwind's scales get named classes — spacing in 4px steps (px-6, py-2.5), the text-* sizes, font weights, rounded-* radii and the shadow-sm/md/lg shadows, read from the tailwindcss package. Anything else becomes an arbitrary value such as px-[13px] or bg-[#4f46e5]. Hover styles use the hover: variant, which in v4 only applies on devices that can hover.

Round the corners further with the border radius generator, build a palette for the button with the Tailwind shade generator, or check any two colours with the contrast checker.