CSS Button Style Generator

How to use 3 steps
  1. Type the Button label and pick a Colour and Style.
  2. Set the Font weight, Corner radius and padding.
  3. Hover the preview to check the hover state, then press Copy Button CSS.
Generated CSS Code

How this tool works

A button is mostly states rather than appearance. The resting style is the easy part; what makes one usable is that it visibly responds to a pointer, and that someone moving through the page by keyboard can see where they are. Both are generated here alongside the base rule, because a button style that covers only the resting state is the one thing this tool used to produce and the reason its output could not be used as it stood.

The label colour is chosen from the fill's relative luminance rather than assumed to be white, since white text on a light fill is the commonest failure in generated button CSS. The hover colour is derived by shifting the fill toward black or white depending on which direction has room. The focus-visible ring is separate from hover on purpose: it appears for keyboard users without appearing for anyone who merely clicked.

What makes a button work

  • Never remove the focus outline without replacing it: outline: none with nothing in its place makes the page unusable by keyboard, and it is the single most common accessibility fault on the web.
  • focus-visible is the modern selector: it shows the ring for keyboard navigation and hides it for mouse clicks, which is what people were trying to achieve when they removed outlines altogether.
  • Touch targets want around 44 pixels: padding and font size together decide the target. A button that looks generous on a desktop can still be an awkward tap.
  • The ghost style needs a visible boundary somewhere: with no background and no border at rest, it depends on its label alone. Fine for a secondary action next to a solid one, weak as the only button on a screen.

A button is mostly states

The resting style is the easy part and the part everyone designs. What makes a button usable is that it visibly responds to a pointer, and that someone moving through the page by keyboard can see where they are.

That is why the [msm_tool slug="css-button-generator"] emits a hover rule and a :focus-visible rule alongside the base one. A button style that covers only the resting state is not finished; it is a rectangle.

focus-visible, and why it exists

For years the pattern was outline: none, because the default focus ring appeared on mouse clicks and looked untidy. The cost was that keyboard users lost any indication of where they were, which makes a page unusable rather than untidy.

:focus-visible resolves it properly. The browser applies it when it judges that a visible indicator is needed — keyboard navigation yes, mouse click no. That is what people were actually trying to achieve when they removed outlines, and it has been supported everywhere current for years.

Two rules follow from that:

  1. Never remove a focus indicator without replacing it. This is the most common accessibility fault on the web, and it is the one with the clearest consequence: a whole category of user cannot operate the page.
  2. Give the replacement real contrast. A focus ring is a non-text interface element and is held to 3:1 against its surroundings. A pale ring on a pale background is present and useless.

An outline-offset of a couple of pixels keeps the ring clear of the button's own edge, which matters on rounded shapes where a tight outline looks like a rendering error.

The label colour is not always white

Generated button CSS defaults to white text with striking regularity, and it fails the moment the fill is light. A yellow button with white text is unreadable and very common.

The generator chooses the label colour from the fill's relative luminance instead: light fills get a dark label, dark fills get a white one. It is a small thing that removes an entire class of mistake, and it is worth doing by hand if your own system does not.

Touch targets

Around 44 pixels in each direction is the widely used minimum, and it comes from padding and font size together rather than from a height you set.

A button that looks generous on a desktop can still be an awkward tap, particularly a text button with tight vertical padding. If the design demands a visually small button, the trick is to keep the visible size and extend the hit area with padding on a wrapper or a pseudo-element.

Solid, outline and ghost

  • Solid — the primary action. One per view, ideally. A screen with four solid buttons has no primary action.
  • Outline — secondary actions beside a solid one. Visible boundary, lower weight.
  • Ghost — tertiary. No background and no border at rest, so it depends entirely on its label. Fine next to something stronger; weak as the only button on a screen, because there is nothing to aim at until you find the words.

The hover state matters most for ghost and outline, since at rest they give the least indication of being interactive.

Deriving the hover colour

Shifting the fill toward black or white by a fixed amount is the usual approach, and the direction should depend on the fill: darken a light colour, lighten a dark one. Doing it in one direction always produces a hover state that disappears on half your palette.

Keep the change modest. A hover that changes the colour dramatically reads as a different button rather than the same button responding.

Buttons and links are not interchangeable

Worth stating because CSS makes them look identical.

A <button> performs an action; an <a> navigates somewhere. They behave differently under the keyboard — space activates a button, enter activates a link — and they are announced differently by screen readers. Styling a link to look like a button is fine; using a <div> with a click handler is not, because it has no role, no keyboard behaviour and no focus by default.

The disabled state

Disabled controls are exempt from the contrast minimum, which is why they can be washed out. That exemption is not a licence to make them indistinguishable from enabled ones — if a user cannot tell which buttons work, the low contrast has caused a different problem.

Better still, where possible, is to leave the button enabled and explain what is missing when it is pressed. A disabled button with no explanation is a dead end.

Frequently Asked Questions

Specific to the CSS Button Style Generator. Broader questions about this category are answered on the category page.

It is chosen from the fill's luminance. White text on a light fill fails contrast, so a light background gets a dark label instead.
It shows the focus ring for keyboard navigation but not for mouse clicks. That is what people are usually after when they remove outlines, without the accessibility cost.
Not without replacing it. A button with no visible focus state is unusable by keyboard, which is the most common accessibility fault on the web.
Around 44 pixels in each direction, which comes from padding and font size together. Desktop-comfortable is often still an awkward tap.
For secondary actions beside a solid primary one. A ghost button with nothing else on the screen gives too little to aim at.

Subscribe to receive notifications about new tools, features, and productivity tips.