CSSStyling Buttons

Styling Buttons

Browsers ship every <button> with a chunky OS-flavored default appearance: a beveled border, a gray or blue-tinted background, platform-specific padding and font. Building a consistent button component means resetting those defaults deliberately, then re-adding the states — hover, focus, active, disabled — that make a button feel alive and usable, rather than just resetting the look and stopping there.
Resetting the native look

CSS
.btn {
  appearance: none;       /* removes native OS button rendering */
  border: none;
  background: none;
  font: inherit;           /* buttons don't inherit font by default */
  padding: 0.6rem 1.25rem;
  border-radius: 8px;
  cursor: pointer;
  color: inherit;
}
Building the interactive states

A button isn't done once it has a nice default look — it needs a distinct visual response for every interaction state a user can put it in.

CSS
.btn--primary {
  background: #2a6df4;
  color: white;
  transition: background-color 0.15s ease, transform 0.1s ease;
}

.btn--primary:hover {
  background: #1d54c9;
}

.btn--primary:active {
  background: #163f99;
  transform: translateY(1px); /* subtle "pressed" feedback */
}

.btn--primary:disabled {
  background: #a9c3f5;
  color: rgba(255, 255, 255, 0.8);
  cursor: not-allowed;
}

/* Visible keyboard-only focus ring — see Focus Styles below */
.btn--primary:focus-visible {
  outline: 2px solid #163f99;
  outline-offset: 2px;
}
Warning
When you reset a button's native styling, you can accidentally reset its focus indicator along with it — many browsers draw a default focus ring as part of the same native rendering that `appearance: none` removes. Never ship a custom button with no visible focus state at all; see [Focus Styles & Keyboard Navigation](/css/focus-styles) for how to design one properly with `:focus-visible`.
Worked example: a reusable button with variants

CSS
<button class="btn btn--primary">Save changes</button>
<button class="btn btn--secondary">Cancel</button>
<button class="btn btn--danger">Delete</button>
<button class="btn btn--primary" disabled>Saving…</button>

.btn {
  appearance: none;
  border: 1px solid transparent;
  font: inherit;
  font-weight: 600;
  padding: 0.6rem 1.25rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.btn--primary {
  background: #2a6df4;
  color: white;
}
.btn--primary:hover { background: #1d54c9; }

.btn--secondary {
  background: white;
  border-color: #ccc;
  color: #1a1a1a;
}
.btn--secondary:hover { background: #f5f5f5; }

.btn--danger {
  background: #d62828;
  color: white;
}
.btn--danger:hover { background: #a91d1d; }

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn:focus-visible {
  outline: 2px solid #2a6df4;
  outline-offset: 2px;
}
Note
Keep hover and active styles subtle and fast (100–200ms transitions) — the goal is to confirm the interaction happened, not to draw attention to the animation itself.
Next
Design the focus ring properly with [Focus Styles & Keyboard Navigation](/css/focus-styles), and check your color choices against [Color Contrast & Readability](/css/color-contrast).