Write minimal, efficient CSS by leveraging browser defaults and modern CSS features. Use when writing CSS, creating stylesheets, setting up base styles, or reviewing CSS for unnecessary declarations.
Write as little CSS as possible. Leverage browser defaults and modern CSS features instead of overriding everything.
Let the browser handle the base font size, which defaults to 100% (typically 16px). Users can adjust this in their browser settings for accessibility.
/* Don't do this */
:root {
font-size: 16px;
}
html {
font-size: 100%;
}
body {
font-size: 1rem;
}
/* Do nothing — the browser already handles this */
Skip declaring color and background-color on the root. Browser defaults work and respect user preferences.
/* Don't do this */
body {
color: #000;
background-color: #fff;
}
/* Do nothing — browser defaults are fine */
Use color-scheme to automatically support light and dark modes based on user system preferences.
:root {
color-scheme: light dark;
}
Use accent-color to change the color of checkboxes, radio buttons, range sliders, and progress bars.
:root {
accent-color: #0066cc; /* Replace with desired color */
}
Make SVG icons inherit the current text color automatically.
:where(svg) {
fill: currentColor;
}
Ensure buttons remain visible in Windows High Contrast Mode by adding explicit borders.
@media (forced-colors: active) {
:where(button) {
border: 1px solid;
}
}
Only apply translucent or glassy effects when the user hasn't requested reduced transparency.
@media (prefers-reduced-transparency: no-preference) {
.glass-panel {
background: oklch(100% 0 0 / 0.8);
backdrop-filter: blur(1rem);
}
}
Enable distinct characters for uppercase I, lowercase l, and slashed zero in San Francisco font.
:root {
font-family: system-ui;
font-feature-settings: "ss06";
}
Prevent widows and improve line breaks.
:where(h1, h2, h3, h4, h5, h6) {
text-wrap: balance;
}
:where(p) {
text-wrap: pretty;
}
Write CSS that works across all languages and writing directions. Use logical properties instead of physical ones.
/* Don't do this */
.card {
margin-left: 1rem;
margin-right: 1rem;
padding-top: 2rem;
padding-bottom: 2rem;
width: 20rem;
height: auto;
}
/* Do this */
.card {
margin-inline: 1rem;
padding-block: 2rem;
inline-size: 20rem;
block-size: auto;
}
Ensure images, videos, and iframes scale proportionally.
:where(img, svg, video, iframe) {
max-inline-size: 100%;
block-size: auto;
}
Provide a baseline hover affordance for all clickable elements.
:where(input:is([type="checkbox"], [type="radio"]), select, label, button) {
cursor: pointer;
}
Ensure all interactive elements have visible, high-contrast focus indicators.
*:focus-visible {
outline: 2px solid;
outline-offset: 2px;
}
Only animate elements when the user hasn't requested reduced motion.
@media (prefers-reduced-motion: no-preference) {
.animated-element {
transition: transform 0.3s ease;
}
}
Apply smooth scrolling only when the user hasn't requested reduced motion.
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
Style components based on their accessibility state rather than creating modifier classes.
/* Don't do this */
.accordion-header--collapsed {
/* collapsed styles */
}
.accordion-header--expanded {
/* expanded styles */
}
/* Do this */
[aria-expanded="false"] {
/* collapsed styles */
}
[aria-expanded="true"] {
/* expanded styles */
}
More examples:
/* Navigation states */
[aria-current="page"] {
font-weight: bold;
}
/* Disabled states */
[aria-disabled="true"] {
opacity: 0.6;
cursor: not-allowed;
}
/* Selected states */
[aria-selected="true"] {
background-color: highlight;
}
/* Invalid form fields */
[aria-invalid="true"] {
border-color: red;
}
Here's a complete minimal base that incorporates all guidelines:
:root {
color-scheme: light dark;
accent-color: #0066cc;
font-family: system-ui;
font-feature-settings: "ss06";
}
*:focus-visible {
outline: 2px solid;
outline-offset: 2px;
}
:where(h1, h2, h3, h4, h5, h6) {
text-wrap: balance;
}
:where(p) {
text-wrap: pretty;
}
:where(img, svg, video, iframe) {
max-inline-size: 100%;
block-size: auto;
}
:where(svg) {
fill: currentColor;
}
:where(input:is([type="checkbox"], [type="radio"]), select, label, button) {
cursor: pointer;
}
@media (forced-colors: active) {
:where(button) {
border: 1px solid;
}
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}