Button reset
Strip all browser default styles from a button — a blank slate for custom design, without losing semantics.
Quick implementation
/* Option A: targeted reset — safer, more explicit */
.btn-reset {
appearance: none;
border: none;
background: none;
font: inherit;
color: inherit;
padding: 0;
margin: 0;
cursor: pointer;
display: inline-flex;
align-items: center;
/* Restore focus ring — never remove without replacement */
}
.btn-reset:focus-visible {
outline: 2px solid oklch(0.72 0.19 265);
outline-offset: 3px;
}
/* Option B: nuclear reset — resets every property to initial */
.btn-reset-all {
all: unset;
cursor: pointer;
display: inline-flex;
/* Manually restore focus visibility after all: unset */
}
.btn-reset-all:focus-visible {
outline: 2px solid oklch(0.72 0.19 265);
outline-offset: 3px;
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building a design system component library.
Goal: Create a CSS button reset class that removes all browser default styles — a clean base for custom button designs — no JavaScript.
Technical constraints:
- Remove: appearance, border, background, padding, margin, font (use inherit), color (use inherit).
- Set cursor: pointer and display: inline-flex so button content aligns correctly.
- Never remove the focus ring without replacing it — always add :focus-visible with outline: 2px solid and outline-offset.
- Use oklch() for focus ring color, not hex or rgba().
- Provide two variants: a targeted reset (individual properties) and a nuclear reset using all: unset.
Framework variant (pick one):
A) Vanilla CSS utility class .btn-reset applied to <button> elements.
B) React — a <ButtonBase> component that applies the reset class and accepts children.
Edge cases to handle:
- all: unset removes display, so set display: inline-flex explicitly after it.
- all: unset also removes :focus-visible styles in some browsers — manually restore the outline.
- Buttons inside flex or grid containers may need align-self or flex-shrink: 0 after the reset — note this.
- If the button wraps an SVG icon, ensure the icon does not receive pointer events: add pointer-events: none to child SVGs.
- Do not use <div role="button"> as a workaround — the native <button> element has built-in keyboard activation (Enter/Space) and accessibility semantics that divs lack.
Return CSS only.
Why this matters in 2026
The <button> element is the correct semantic choice for interactive controls that trigger an action — but browser defaults make it look like a physical 3D button from 1995. Developers reach for <div> or <span> to avoid the styling challenge, losing built-in keyboard accessibility and ARIA semantics in the process. A button reset removes the visual baggage while keeping everything that makes <button> valuable.
The logic
The targeted reset removes each problematic default individually. appearance: none removes OS-level widget rendering. border: none and background: none clear the visible frame. font: inherit and color: inherit pull typography from the parent, fixing the system-font mismatch. padding: 0 removes the browser's internal padding, which varies between browsers. cursor: pointer restores the hand cursor that users expect on clickable elements.
The all: unset shorthand resets every CSS property to its initial or inherited value in one declaration. It is more thorough but also more destructive — it removes display, box-sizing, and even :focus-visible behavior in some browsers. Use it when you want a truly blank slate and are willing to re-declare everything explicitly.
Accessibility & performance
The most common accessibility mistake with button resets is removing :focus styles without a replacement. Always include :focus-visible with a visible outline after any reset — keyboard-only users navigate entirely by focus indicators. The :focus-visible pseudo-class (supported in all modern browsers) only shows the outline when the user navigates via keyboard, so it does not interfere with mouse-click aesthetics. Never use outline: none or outline: 0 without a replacement in the same rule.