The full CSS reference you keep searching for. Selectors, box model, flexbox, grid, typography, animations, custom properties, and responsive patterns — all in one place.
Quick reference
The 25 properties and patterns that cover 90% of CSS work.
| Snippet | What it does |
|---|---|
box-sizing: border-box |
Include padding/border in width calculation |
display: flex |
Enable flexbox layout |
display: grid |
Enable grid layout |
margin: 0 auto |
Centre a block element horizontally |
position: relative |
Positioned parent for absolute children |
position: absolute; inset: 0 |
Fill parent element completely |
position: sticky; top: 0 |
Stick to top on scroll |
overflow: hidden |
Clip content and establish BFC |
gap: 1rem |
Spacing in flex/grid (replaces margin hacks) |
flex: 1 |
Grow to fill available space |
grid-template-columns: repeat(3, 1fr) |
3 equal columns |
place-items: center |
Centre children horizontally + vertically |
aspect-ratio: 16 / 9 |
Lock element's aspect ratio |
max-width: 65ch |
Optimal reading line length |
font-size: clamp(1rem, 2.5vw, 1.5rem) |
Fluid typography |
color: hsl(220 90% 50%) |
Modern HSL colour (space-separated syntax) |
opacity: 0; visibility: hidden |
Hide without removing from layout |
transform: translateY(-50%) |
Vertical offset trick |
transition: all 0.2s ease |
Animate all changing properties |
will-change: transform |
GPU-accelerate an animated element |
:is(h1, h2, h3) |
Match multiple selectors cleanly |
:where(.btn) |
Same as :is() but zero specificity |
--color-primary: #3b82f6 |
Define a CSS custom property |
var(--color-primary, blue) |
Use custom property with fallback |
@media (prefers-color-scheme: dark) |
Dark mode media query |
Selectors
Basic selectors
* { } /* universal */
div { } /* element */
.card { } /* class */
#hero { } /* id */
[href] { } /* attribute present */
[type="text"]{ } /* attribute value */
[class~="a"] { } /* attribute contains word */
[href^="https"]{ } /* attribute starts with */
[href$=".pdf"] { } /* attribute ends with */
[href*="docs"] { } /* attribute contains */
Combinators
div p { } /* descendant (any depth) */
div > p { } /* direct child */
h2 + p { } /* adjacent sibling (immediately after) */
h2 ~ p { } /* general sibling (any after) */
Pseudo-classes
/* State */
:hover :focus :active
:checked :disabled :read-only
:focus-within /* parent when child is focused */
:focus-visible /* keyboard-focus only */
/* Tree position */
:first-child :last-child :only-child
:nth-child(2) /* 2nd child */
:nth-child(2n) /* even children */
:nth-child(2n+1) /* odd children */
:nth-child(3n+1) /* every 3rd, starting at 1 */
:nth-last-child(1) /* last child */
:first-of-type :last-of-type
:nth-of-type(2n)
/* Content */
:empty /* no children or text */
:not(.active) /* negation */
:is(h1, h2, h3) /* matches any in list */
:where(.card, .panel) /* same as :is but 0 specificity */
:has(> img) /* parent selector */
/* Links */
:link :visited :any-link
Pseudo-elements
::before /* insert content before */
::after /* insert content after */
::first-line /* style first line */
::first-letter /* style first character */
::placeholder /* input placeholder text */
::selection /* highlighted text */
::marker /* list item bullet/number */
::backdrop /* fullscreen/dialog backdrop */
Specificity order (low → high): * (0) → element/pseudo-element (1) → class/attribute/pseudo-class (10) → id (100) → inline style (1000) → !important
Box model
┌──────────────────────────────┐
│ margin │
│ ┌────────────────────────┐ │
│ │ border │ │
│ │ ┌──────────────────┐ │ │
│ │ │ padding │ │ │
│ │ │ ┌────────────┐ │ │ │
│ │ │ │ content │ │ │ │
│ │ │ └────────────┘ │ │ │
│ │ └──────────────────┘ │ │
│ └────────────────────────┘ │
└──────────────────────────────┘
/* Always set at root level */
*, *::before, *::after {
box-sizing: border-box; /* padding + border included in width */
}
/* Shorthand order: top right bottom left (clockwise) */
margin: 10px; /* all sides */
margin: 10px 20px; /* top/bottom | left/right */
margin: 10px 20px 30px; /* top | sides | bottom */
margin: 10px 20px 30px 40px;/* top right bottom left */
padding: 1rem 2rem; /* same shorthand */
/* Border */
border: 1px solid #ccc; /* width style color */
border-radius: 8px; /* round corners */
border-radius: 50%; /* circle (on square) */
border-radius: 1rem 0 1rem 0; /* top-left, top-right, bottom-right, bottom-left */
outline: 2px solid blue; /* outside border (no layout impact) */
outline-offset: 4px; /* space between element and outline */
Display
display: block; /* full width, new line */
display: inline; /* flow with text, no width/height */
display: inline-block; /* inline position, block sizing */
display: flex; /* flexbox container */
display: inline-flex; /* inline flexbox container */
display: grid; /* grid container */
display: inline-grid; /* inline grid container */
display: none; /* removed from layout */
display: contents; /* element disappears, children promoted */
display: table; /* behave like <table> */
Flexbox
/* Container */
.container {
display: flex;
flex-direction: row; /* row | row-reverse | column | column-reverse */
flex-wrap: wrap; /* nowrap | wrap | wrap-reverse */
justify-content: space-between; /* main axis */
align-items: center; /* cross axis */
align-content: flex-start; /* multi-line cross axis */
gap: 1rem; /* row and column gap */
gap: 1rem 2rem; /* row-gap | column-gap */
}
/* Item */
.item {
flex: 1; /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
flex: 0 0 200px; /* don't grow, don't shrink, 200px wide */
flex-grow: 1; /* grow factor */
flex-shrink: 0; /* don't shrink */
flex-basis: 300px; /* starting size */
align-self: flex-end; /* override align-items for this item */
order: -1; /* reorder without changing HTML */
}
justify-content values: flex-start · flex-end · center · space-between · space-around · space-evenly
align-items values: stretch · flex-start · flex-end · center · baseline
Grid
/* Container */
.grid {
display: grid;
grid-template-columns: 200px 1fr 2fr; /* explicit columns */
grid-template-columns: repeat(3, 1fr); /* 3 equal columns */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); /* responsive */
grid-template-rows: auto 1fr auto; /* header, main, footer */
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 1rem; /* row and column gap */
gap: 1rem 2rem; /* row-gap | column-gap */
}
/* Item */
.item {
grid-column: 1 / 3; /* start / end (line numbers) */
grid-column: span 2; /* span 2 columns */
grid-row: 2 / 4; /* rows 2 to 4 */
grid-area: header; /* match named area */
justify-self: center; /* horizontal alignment in cell */
align-self: end; /* vertical alignment in cell */
}
/* Centre everything */
.grid { place-items: center; } /* align-items + justify-items */
Grid functions:
| Function | Use |
|---|---|
fr |
Fractional unit of remaining space |
minmax(min, max) |
Clamp track size |
repeat(n, size) |
Repeat track definition |
auto-fill |
Fill row with as many tracks as fit |
auto-fit |
Same but collapse empty tracks |
fit-content(200px) |
Grow up to max, shrink to content |
Positioning
position: static; /* default — normal flow */
position: relative; /* offset from normal position; establishes stacking context */
position: absolute; /* remove from flow, position relative to nearest non-static ancestor */
position: fixed; /* relative to viewport, stays on scroll */
position: sticky; /* hybrid: relative until scroll threshold, then fixed */
/* Offset properties */
top: 0; right: 0; bottom: 0; left: 0;
inset: 0; /* shorthand for all four: top right bottom left */
inset: 10px 20px; /* top/bottom | left/right */
/* Z-index (requires non-static positioning or opacity/transform/etc.) */
z-index: 1; /* higher = in front */
z-index: -1; /* behind parent */
Stacking context is created by: position + z-index (not auto) · opacity < 1 · transform · filter · will-change · isolation: isolate
Typography
/* Font */
font-family: 'Inter', system-ui, sans-serif;
font-size: 1rem; /* 16px default */
font-size: clamp(1rem, 2vw, 1.25rem); /* fluid size */
font-weight: 400; /* normal */
font-weight: 700; /* bold */
font-style: italic;
font-variant: small-caps;
font: italic 700 1.2rem/1.5 'Inter', sans-serif; /* shorthand */
/* Line spacing */
line-height: 1.5; /* unitless preferred (1.5× font-size) */
letter-spacing: 0.05em;
word-spacing: 0.1em;
/* Alignment */
text-align: left | center | right | justify;
vertical-align: middle; /* inline/table-cell alignment */
/* Decoration */
text-decoration: underline;
text-decoration: none; /* remove link underline */
text-transform: uppercase | lowercase | capitalize;
text-indent: 2em;
/* Overflow */
white-space: nowrap; /* prevent wrapping */
overflow: hidden;
text-overflow: ellipsis; /* show "…" on overflow */
/* Multiline ellipsis */
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
System font stacks:
/* Modern sans-serif */
font-family: system-ui, -apple-system, sans-serif;
/* Monospace */
font-family: ui-monospace, 'Cascadia Code', 'Fira Code', monospace;
/* Serif */
font-family: ui-serif, Georgia, 'Times New Roman', serif;
Colors
/* Formats */
color: red; /* named */
color: #3b82f6; /* hex (RGB) */
color: #3b82f680; /* hex with alpha */
color: rgb(59 130 246); /* rgb (modern space syntax) */
color: rgb(59 130 246 / 0.5); /* rgb with alpha */
color: hsl(217 91% 60%); /* hue saturation lightness */
color: hsl(217 91% 60% / 0.5); /* hsl with alpha */
color: oklch(0.65 0.2 250); /* perceptually uniform (best for design) */
/* Common properties */
color: ...; /* text colour */
background-color: ...; /* background */
border-color: ...; /* border */
outline-color: ...; /* outline */
caret-color: ...; /* cursor in inputs */
accent-color: blue; /* native checkbox/radio/range colour */
/* Current colour keyword */
color: navy;
border: 1px solid currentColor; /* inherits from color property */
/* Transparent */
background-color: transparent;
background-color: rgb(0 0 0 / 0);
Backgrounds
background-color: #f0f0f0;
background-image: url('image.jpg');
background-size: cover; /* fill container (may crop) */
background-size: contain; /* fit inside (may letterbox) */
background-size: 100% auto;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed; /* parallax effect */
background-clip: text; /* clip to text (with -webkit-) */
background-origin: content-box; /* where image starts */
/* Shorthand */
background: url('img.jpg') center / cover no-repeat #f0f0f0;
/* Gradients as backgrounds */
background: linear-gradient(to right, #3b82f6, #8b5cf6);
background: linear-gradient(135deg, #ff6b6b 0%, #ffd93d 100%);
background: radial-gradient(circle at center, #3b82f6, transparent);
background: conic-gradient(from 0deg, red, yellow, green, red);
/* Multiple backgrounds (last listed = bottom) */
background:
url('top.png') no-repeat center top,
url('bottom.png') no-repeat center bottom,
linear-gradient(to bottom, #fff, #f0f0f0);
Transitions
/* Syntax: property duration timing-function delay */
transition: color 0.2s ease;
transition: all 0.3s ease-in-out;
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease;
/* Timing functions */
transition-timing-function: ease; /* slow-fast-slow (default) */
transition-timing-function: linear; /* constant speed */
transition-timing-function: ease-in; /* slow start */
transition-timing-function: ease-out; /* slow end */
transition-timing-function: ease-in-out; /* slow start and end */
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
transition-timing-function: steps(4, end); /* jump steps */
/* Don't transition these (they cause layout reflow) */
/* width, height, top, left, margin, padding */
/* Prefer: transform and opacity — GPU composited */
Animations
/* Define keyframes */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
/* Apply animation */
.element {
animation: fadeIn 0.4s ease forwards;
/* Individual properties */
animation-name: fadeIn;
animation-duration: 0.4s;
animation-timing-function: ease;
animation-delay: 0.1s;
animation-iteration-count: 1; /* or: infinite */
animation-direction: normal; /* normal | reverse | alternate | alternate-reverse */
animation-fill-mode: forwards; /* none | forwards | backwards | both */
animation-play-state: running; /* running | paused */
}
/* Multiple animations */
animation: fadeIn 0.4s ease forwards, pulse 2s ease infinite 0.5s;
/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Transforms
/* 2D transforms */
transform: translateX(20px);
transform: translateY(-50%);
transform: translate(20px, -50%);
transform: scale(1.2);
transform: scale(1.2, 0.8); /* scaleX, scaleY */
transform: rotate(45deg);
transform: skew(10deg, 5deg);
/* Chain transforms (applied right to left) */
transform: translateX(-50%) rotate(45deg) scale(1.2);
/* 3D transforms */
transform: translateZ(100px);
transform: rotateX(45deg);
transform: rotateY(45deg);
transform: perspective(500px) rotateY(30deg);
/* Transform origin */
transform-origin: center; /* default */
transform-origin: top left;
transform-origin: 50% 100%;
transform-origin: 0 0;
/* Perspective on parent */
.parent { perspective: 1000px; }
.child { transform: rotateY(30deg); }
CSS custom properties (variables)
/* Define at root (global scope) */
:root {
--color-primary: #3b82f6;
--color-primary-dark: #1d4ed8;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 2rem;
--font-body: 'Inter', system-ui, sans-serif;
--radius: 0.5rem;
--shadow: 0 1px 3px rgb(0 0 0 / 0.12);
}
/* Use with var() */
.button {
background: var(--color-primary);
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
/* Fallback value */
color: var(--color-text, #1a1a1a);
/* Override in component scope */
.card {
--spacing-md: 1.5rem; /* local override */
}
/* Update via JavaScript */
document.documentElement.style.setProperty('--color-primary', '#ef4444');
/* Dark mode with variables */
:root {
--bg: #ffffff;
--text: #1a1a1a;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #ffffff;
}
}
Media queries
/* Breakpoints (mobile-first approach) */
/* Base: mobile */
/* sm: 640px */
/* md: 768px */
/* lg: 1024px */
/* xl: 1280px */
/* 2xl: 1536px */
/* Mobile-first (min-width) */
@media (min-width: 768px) { /* tablet and up */ }
@media (min-width: 1024px) { /* desktop and up */ }
/* Desktop-first (max-width) */
@media (max-width: 767px) { /* mobile only */ }
/* Range (CSS Media Queries Level 4) */
@media (768px <= width < 1024px) { }
/* Feature queries */
@media (prefers-color-scheme: dark) { }
@media (prefers-reduced-motion: reduce) { }
@media (prefers-contrast: high) { }
@media (hover: hover) { } /* device supports hover */
@media (pointer: coarse) { } /* touch device */
@media print { } /* print styles */
/* Container queries (modern) */
.wrapper { container-type: inline-size; }
@container (min-width: 600px) {
.card { display: flex; }
}
/* Combining with logic */
@media (min-width: 600px) and (max-width: 900px) { }
@media (min-width: 600px) or (orientation: landscape) { }
@media not (hover: hover) { }
Common patterns
Centre horizontally and vertically
/* Flexbox */
.parent {
display: flex;
justify-content: center;
align-items: center;
}
/* Grid */
.parent {
display: grid;
place-items: center;
}
/* Absolute position */
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Full-bleed layout with constrained content
.container {
width: min(100% - 2rem, 70rem); /* max width with side padding */
margin-inline: auto; /* centre */
}
Sticky header
header {
position: sticky;
top: 0;
z-index: 100;
background: white;
backdrop-filter: blur(8px);
}
Fluid typography
html { font-size: clamp(14px, 1.5vw, 18px); }
h1 { font-size: clamp(2rem, 5vw, 4rem); }
CSS card
.card {
background: white;
border-radius: 0.75rem;
padding: 1.5rem;
box-shadow: 0 1px 3px rgb(0 0 0 / 0.1), 0 1px 2px rgb(0 0 0 / 0.06);
transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.card:hover {
box-shadow: 0 10px 25px rgb(0 0 0 / 0.15);
transform: translateY(-2px);
}
Responsive grid (auto-fill)
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1.5rem;
}
Visually hidden (accessible)
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
Aspect ratio box
.video-wrapper {
aspect-ratio: 16 / 9;
width: 100%;
overflow: hidden;
}
.video-wrapper iframe {
width: 100%;
height: 100%;
}
Custom scrollbar
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: #888; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #555; }
/* Standard (Firefox) */
* { scrollbar-width: thin; scrollbar-color: #888 #f1f1f1; }
Units reference
| Unit | Relative to | Use case |
|---|---|---|
px |
Device pixel (scaled) | Borders, shadows |
rem |
Root font-size (16px) | Spacing, font-size |
em |
Current font-size | Component-local spacing |
% |
Parent dimension | Fluid widths |
vw |
Viewport width | Fluid layouts |
vh |
Viewport height | Hero sections |
dvh |
Dynamic viewport height | Mobile (accounts for browser chrome) |
ch |
Width of "0" character | Text column widths |
fr |
Fraction (grid only) | Grid tracks |
min-content |
Smallest without overflow | Grid track sizing |
max-content |
Ideal (no wrap) | Grid track sizing |
fit-content |
Between min and max | Grid track sizing |
Common mistakes
| Mistake | What happens | Fix |
|---|---|---|
box-sizing: content-box (default) |
Padding/border add to stated width | Set border-box globally |
z-index not working |
Element not in its own stacking context | Add position: relative |
height: 100% on child has no effect |
Parent has no explicit height | Use min-height: 100vh or flexbox |
margin: auto not centring |
Element is display: inline |
Use display: block |
transition: all |
Expensive, animates unintended properties | Specify exact properties |
!important everywhere |
Specificity wars | Refactor selectors or use :is()/:where() |
float for layout |
Fragile, removed from flow | Use flexbox or grid |
Animating width/height |
Triggers layout on every frame | Use transform: scaleX() instead |
CSS vs preprocessors
| Feature | CSS | SCSS/Sass | Less | Stylus |
|---|---|---|---|---|
| Variables | --var (runtime) |
$var (compile time) |
@var |
var |
| Nesting | Yes (native 2024) | Yes | Yes | Yes |
| Mixins | No | @mixin/@include |
.mixin() |
Limited |
| Functions | calc(), etc. |
Custom functions | Functions | Functions |
| Loops | No | @each, @for |
Recursive mixins | for … in |
| Build step | No | Yes | Yes | Yes |
| Browser support | All | All (compiled) | All (compiled) | All (compiled) |
FAQ
What is the difference between em and rem?
rem is relative to the root element's font-size (usually 16px). em is relative to the current element's own font-size, so it compounds when nested. Use rem for most sizing to keep things predictable.
Why doesn't z-index work?
z-index only affects elements that have a stacking context. A stacking context is created by position (relative/absolute/fixed/sticky) combined with a non-auto z-index, or by opacity < 1, transform, filter, isolation: isolate, and others. Also, z-index only compares elements within the same stacking context.
What is the difference between visibility: hidden and display: none?
display: none removes the element from the layout entirely — it takes no space. visibility: hidden hides it visually but preserves the space it occupies. opacity: 0 is similar to visibility: hidden but still fires events.
When should I use flexbox vs grid?
Flexbox is one-dimensional — use it for rows or columns of items where the content dictates size. Grid is two-dimensional — use it when you need to control both rows and columns simultaneously. In practice: flexbox for components (nav, buttons, form rows), grid for page layouts and card grids.
How do I make a website dark-mode compatible?
Use CSS custom properties for colours. Define light values in :root and override them inside @media (prefers-color-scheme: dark). For a toggle, you can switch a data-theme="dark" attribute on <html> instead of relying on the media query.
What does will-change: transform do?
It hints to the browser that an element's transform (or another property) will change, allowing it to promote the element to its own compositor layer ahead of time. This avoids the jank of layer promotion during an animation. Use it sparingly — too many layers consume GPU memory.