CSS Button Styles
Complete guide to styling CSS buttons — backgrounds, borders, hover effects, transitions, focus states, and accessibility.
Overview
Buttons are the primary interactive elements in web interfaces. CSS button styling involves background-color, color, border, border-radius, padding, font, box-shadow, and pseudo-classes like :hover, :focus-visible, and :active. Well-styled buttons communicate clickability, provide feedback on interaction, and maintain accessibility for keyboard and screen reader users. This guide covers styling patterns from basic to advanced.
Syntax
button { background: ...; color: ...; border: ...; padding: ...; ... }Values & Keywords
Practical Examples
.btn-primary {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 0.625rem 1.25rem;
font: inherit;
font-weight: 500;
color: white;
background: #3b82f6;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s, transform 0.15s;
}
.btn-primary:hover {
background: #2563eb;
}
.btn-primary:active {
transform: scale(0.98);
}
.btn-primary:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}.btn-ghost {
padding: 0.625rem 1.25rem;
font: inherit;
font-weight: 500;
color: #3b82f6;
background: transparent;
border: 1.5px solid #3b82f6;
border-radius: 8px;
cursor: pointer;
transition: all 0.15s;
}
.btn-ghost:hover {
background: #3b82f6;
color: white;
}.btn-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
padding: 0;
font: inherit;
color: #6b7280;
background: transparent;
border: 1px solid #e5e7eb;
border-radius: 8px;
cursor: pointer;
transition: all 0.15s;
}
.btn-icon:hover {
color: #1f2937;
background: #f3f4f6;
border-color: #d1d5db;
}.btn-loading {
position: relative;
color: transparent;
pointer-events: none;
}
.btn-loading::after {
content: "";
position: absolute;
inset: 0;
margin: auto;
width: 18px;
height: 18px;
border: 2px solid rgba(255, 255, 255, 0.3);
border-top-color: white;
border-radius: 50%;
animation: spin 0.6s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}Try it visually
Use our interactive button CSS generator to experiment with values and see the result in real-time. Copy production-ready CSS, cross-browser CSS, or Tailwind classes with one click.
Open CSS Button Styles ToolCommon Patterns
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 0.5em 1.25em;
font: inherit;
font-weight: 500;
border: 1.5px solid transparent;
border-radius: 8px;
cursor: pointer;
transition: all 0.15s;
}
.btn-primary {
background: #3b82f6;
color: white;
}
.btn-secondary {
background: #f1f5f9;
color: #1e293b;
}
.btn-destructive {
background: #ef4444;
color: white;
}
.btn-outline {
background: transparent;
border-color: #e2e8f0;
color: #1e293b;
}.btn-group {
display: inline-flex;
}
.btn-group .btn {
border-radius: 0;
}
.btn-group .btn:first-child {
border-radius: 8px 0 0 8px;
}
.btn-group .btn:last-child {
border-radius: 0 8px 8px 0;
}
.btn-group .btn + .btn {
border-left: 1px solid rgba(0, 0, 0, 0.1);
}.btn-slide {
position: relative;
overflow: hidden;
z-index: 0;
}
.btn-slide::before {
content: "";
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.1);
transform: translateX(-100%);
transition: transform 0.3s;
z-index: -1;
}
.btn-slide:hover::before {
transform: translateX(0);
}Tips & Best Practices
- 1
Always provide :focus-visible styles — never remove the default outline without adding a replacement. Keyboard users rely on visible focus indicators to navigate.
- 2
Use em units for padding so buttons scale proportionally with font size. padding: 0.5em 1.5em adapts to both small and large button variants.
- 3
Maintain a minimum touch target of 44x44px (WCAG 2.5.5). Even if the visual button is smaller, use padding or min-width/min-height to ensure the interactive area meets this threshold.
- 4
Keep transition durations under 200ms for button states. Longer animations feel sluggish and make the UI feel unresponsive.
- 5
Use cursor: pointer and user-select: none on custom buttons. Add -webkit-tap-highlight-color: transparent on mobile to remove the default tap highlight.
Browser Support
All properties universally supported. :focus-visible requires Chrome 86+, Firefox 85+, Safari 15.4+.
Related CSS Guides
border-radiusCSS border-radius
Complete guide to the CSS border-radius property — syntax, values, per-corner control, elliptical corners, and browser support.
box-shadowCSS box-shadow
Complete guide to the CSS box-shadow property — syntax, multiple layers, inset shadows, spread radius, and performance tips.
colorCSS Color Formats
Complete guide to CSS color formats — HEX, RGB, HSL, OKLCH, named colors, transparency, and color-mix().
background-image (gradients)CSS Gradients
Complete guide to CSS gradients — linear-gradient, radial-gradient, conic-gradient syntax, color stops, and advanced patterns.
CSS Button Styles — FAQ
Common questions about button CSS and how to use it effectively.
How do I remove default button styles?
Use appearance: none; background: none; border: none; padding: 0; font: inherit; cursor: pointer; to reset browser defaults, then apply your custom styles on top.
How do I make a button accessible?
Ensure 4.5:1 color contrast for text, provide :focus-visible styles for keyboard users, use semantic <button> elements (not divs), maintain minimum 44x44px touch targets, and add aria-label for icon-only buttons.
How do I create a gradient button with hover?
Use background-image: linear-gradient(...) with background-size: 200%. On hover, shift background-position to reveal the second half. Alternatively, use a pseudo-element overlay that fades in on hover.
Should I use <button> or <a> for clickable elements?
Use <button> for actions (submit, toggle, open modal). Use <a> for navigation (links to other pages or anchors). The distinction matters for accessibility — screen readers announce them differently, and keyboard handling differs (Enter for links, Enter/Space for buttons).
How do I disable a button properly?
Use the disabled attribute on <button>. Style it with .btn:disabled { opacity: 0.5; cursor: not-allowed; }. Do NOT use pointer-events: none alone — it prevents click but also prevents keyboard interaction and screen reader access.