CSS & Web Design

CSS Button Guide: Hover, Active States and Accessible Design

By Smart Tools Utility Team · Published October 7, 2026 · Updated October 7, 2026 · 8 min read

A button looks simple, but a good one is really four styles in one: how it looks at rest, when the pointer is over it, while it is being pressed, and when someone reaches it with the keyboard. The CSS Button Style Generator writes the first three for you and hands you matching HTML. This guide walks through the controls, shows what each effect really outputs, and then covers what a generator cannot decide for you: contrast, size, focus, fonts and whether you should be using a button or a link at all. We tested the generated code in separate test pages in a Chromium browser, and one finding about the tool's preview is important enough to put first.

Read this first: the Live Preview does not show your styling

The tool's Live Preview is meant to be a real button wearing the generated CSS. At the time of writing it is not. The CSS the tool produces targets the class .btn-custom, but the preview button has a different class (preview-btn-custom), so none of your colours, padding, radius or hover effects appear on it. In our test the preview stayed a plain grey browser-default button, about 83 by 30 pixels, whatever the settings (the label text does update). The code box and the HTML box are correct, and the generated code worked as expected in every test below.

So treat the CSS Code box as the real result, and check your design in a test page or on your own site: paste the CSS and HTML into a file, open it, and hover and click. The screenshots later in this guide were made that way.

The controls, step by step

  1. Button Text. Up to 30 characters. If you clear it, the HTML falls back to Click Me.
  2. Background and Text Color pickers.
  3. Border Radius: 0 to 50px.
  4. Padding (V / H): two sliders, the first for vertical (4 to 30px) and the second for horizontal (8 to 60px).
  5. Font Size: 10 to 28px.
  6. Border Width: 0 to 6px, and Border Color.
  7. Hover Effect: None, Darken, Lift + Shadow, Grow or Glow.
  8. Click Effect: None, Press Down or Shrink.
  9. Use Copy CSS and Copy HTML.
The Button Generator with the text Get started, a blue background, radius 10, padding 14 and 32, Lift plus Shadow hover and Press Down click, next to the generated CSS
Settings for a blue button with a lift-and-shadow hover and a press-down click, and the CSS they produce. The controls and code were captured from the tool.

That example produces:

.btn-custom {
  background-color: #1d4ed8;
  color: #ffffff;
  border-radius: 10px;
  padding: 14px 32px;
  font-size: 17px;
  border: 0px solid #831843;
  cursor: pointer;
  transition: all 0.2s ease;
}
.btn-custom:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
}
.btn-custom:active {
  transform: translateY(1px);
}
<button class="btn-custom">Get started</button>

Choosing None for an effect leaves its block out entirely rather than writing an empty one. The border line is always written, even at 0px width, which is harmless.

What each effect outputs

The base rule includes transition: all 0.2s ease, so every effect animates over a fifth of a second. If you only change a few properties, you can narrow it, for example transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease.

Hover and click effects combine, and the click wins. The :active rule comes after the :hover rule, and both set transform. We pressed the mouse while hovering and read the computed values. With Lift + Press, the hovered button sat at translateY(-3px), and while pressed it was at translateY(1px), so it moves 4px down but the lift shadow stays. With Grow + Shrink, the 1.05 scale became 0.95. With Glow + Shrink, the glow stayed while the button shrank. The pairs behave sensibly, but remember that the pressed state replaces the hover transform rather than adding to it.

Ready to style a button?

Open the Button Generator

Colour contrast: the number that matters most

The tool will let you choose any pair of colours, including ones that are hard to read. The standard measure is the WCAG contrast ratio, where 4.5 to 1 is the common minimum for normal-sized text (3 to 1 for large text). We calculated it for a few typical pairings with the standard formula:

Bright "friendly" colours often fail with white text. Switch the Text Color to a very dark one (for example #111827 on #fbbf24 gives 10.63), or darken the background. Check the hover colour too: the darker hover of the default pink (#ba2165) has a ratio of 6.01, so darkening usually helps contrast, but a Glow or Lift effect does not change it at all.

Size, touch targets and spacing

The padding sliders let you go small. With the smallest settings (4px vertical, 8px horizontal, 10px font) a button measured only about 29 by 19 pixels in our test, which is hard to tap. The default (12px by 28px, 16px font, Arial) measured 117 by 42 pixels, and the blue example above (14px by 32px, 17px) is 48px tall. Accessibility guidelines set a minimum target size of 24 CSS pixels in each direction (WCAG 2.2, level AA) and recommend 44 pixels for comfortable touch (level AAA). For primary actions on mobile, keep to roughly 44px of height, and leave space between neighbouring buttons.

What the generated code leaves out

Font

The CSS sets font-size but not font-family or font-weight. A <button> does not inherit the page's font by default: in our test page with a Georgia body, the generated button rendered in Arial at weight 400. Add font-family: inherit; (and a weight such as font-weight: 600;) so the button matches your page.

Keyboard focus

Nothing in the code removes the browser's focus ring, and in our test tabbing to the button showed the default ring (outline: auto 1px). Keep it. If you want a custom one, add a :focus-visible rule with a clearly visible outline; never write outline: none without a replacement. Note also that the hover and press effects only help mouse and touch users.

Disabled and loading states

There is no :disabled style. If your button can be disabled, add something like .btn-custom:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }, because otherwise the hover lift would still play on a disabled button.

Hover on touch screens

If you do not want hover effects on devices without a hovering pointer, wrap the hover rule in @media (hover: hover) { ... }.

The tool outputs a <button>, which is right for actions: submitting a form, opening a dialog, toggling something. If clicking should take someone to another page, a link (<a href>) is the correct element, and you can style it with the same class. It needs two extra lines: we tested the generated CSS on an anchor, and it stayed display: inline with an underline. Adding display: inline-block; text-decoration: none; restored the button look and the full 48px height.

Three renderings of the same blue Get started button: at rest, lifted with a shadow on hover, and pressed one pixel down
The generated CSS rendered in a test page in its three states. The font was set to inherit for the picture; the tool's own code does not include it.

When you paste the HTML, remember it uses the class name btn-custom and no type attribute. Inside a form, a button without a type submits the form, so add type="button" when it should not. If you need several button styles on one page, rename the class in both the CSS and HTML for each one; the tool always writes btn-custom.

Privacy and escaping

The tool runs in your browser: no requests carried our settings, and nothing is stored between sessions. One detail to be aware of with the text field: the HTML box writes your text exactly as typed. When we entered A & B <b>x</b>, the HTML output was <button class="btn-custom">A & B <b>x</b></button>, with the tags unescaped, so they would render as bold in your page. That is useful if you want an inline icon, but write &amp; and &lt; yourself for literal characters.

Quick answers

Can I add a gradient or an icon? Not in the tool. Edit the copied CSS (background: linear-gradient(...) replaces the background colour) or the HTML.

Why does my hover effect not show on a black button? The Darken effect multiplies the colour by 0.85, which leaves pure black unchanged. Use Lift, Grow or Glow, or choose a very dark grey.

Does it write vendor prefixes? No. The properties used (transition, transform, box-shadow) work unprefixed in current browsers.

How do I make it full width? Add width: 100% to the class, or display: block for an anchor.

Ready to style a button?

Open the Button Generator