CSS

Complete CSS cheat sheet covering the cascade, selectors, box model, flexbox, grid, positioning, animations, and responsive design.

17 sections31 cards

When multiple rules target the same element, CSS uses three factors in order: origin → specificity → order.

Origin — inline styles beat stylesheet rules. !important overrides everything (avoid unless absolutely needed).

Specificity — a score calculated per selector. Higher score wins. The scoring (roughly):

· Inline style: 1000

· ID selector #id: 100

· Class, attribute, pseudo-class .class / [attr] / :hover: 10

· Element, pseudo-element div / ::before: 1

· Universal selector *: 0

Order — when specificity ties, the rule that appears last in the CSS wins.

Common gotcha: a class selector always beats element selectors no matter how many you chain. div div div (score 3) still loses to .box (score 10).

* — universal, selects everything

div — element type

.class — class

#id — ID (unique per page)

[attr] — has attribute

[attr="val"] — exact match

[attr^="val"] — starts with

[attr$="val"] — ends with

[attr*="val"] — contains

A B — descendant (any depth)

A > B — direct child only

A + B — adjacent sibling (immediately after)

A ~ B — general sibling (any after)

A, B — group (applies to both)

:hover :focus :active — interaction states

:visited — visited links

:first-child :last-child

:nth-child(n)n can be number, odd, even, or formula like 2n+1

:nth-of-type(n) — like nth-child but among same-type siblings

:not(.class) — negation

:is(h1, h2, h3) — matches any in list

:where() — like :is but zero specificity

:has(img) — parent that contains img. Huge — now supported in all browsers.

:checked :disabled :required — form states

:empty — no children

:root — the html element. Used for CSS custom properties.

::before ::after — insert content before/after element. Requires content: "" property even if empty.

::placeholder — style input placeholder text

::selection — style highlighted text

::first-line ::first-letter

::marker — style list bullets/numbers

Double colon :: is modern standard. Single colon :before is legacy but still works.

Every element is a rectangular box with four layers from inside out: content → padding → border → margin.

box-sizing: content-box (default) — width/height only counts content. Padding and border add to total size. Very confusing.

box-sizing: border-box — width/height includes padding and border. What you set is what you get. Always use this. Put it on *.

Margin collapse — vertical margins between block elements collapse into one. Two adjacent elements with margin-bottom: 20px and margin-top: 30px result in 30px gap (the larger one), not 50px. Horizontal margins never collapse.

outline — like border but doesn't take up space. Doesn't affect layout. Often used for focus rings.

block — full width, starts new line

inline — flows with text, no width/height control

inline-block — flows with text but respects width/height/padding

none — removed from layout entirely (unlike visibility: hidden which hides but keeps space)

flex — enables flexbox on container

inline-flex — flex but inline

grid — enables grid on container

inline-grid — grid but inline

contents — element itself disappears, children act as if directly in parent

display: none — element is gone. No space. Not accessible to screen readers.

visibility: hidden — invisible but space is preserved. Still in DOM.

opacity: 0 — invisible but space preserved. Still interactive (can be clicked).

For accessibility, use clip technique for visually hidden but screen-reader-accessible content (the sr-only pattern).

Flexbox handles layout in one direction at a time (row or column). Parent is the flex container, children are flex items.

display: flex — activates flexbox

flex-direction: row | row-reverse | column | column-reverse

flex-wrap: nowrap | wrap | wrap-reverse — wrap to next line if overflow

justify-content — aligns along main axis (horizontal if row): flex-start | flex-end | center | space-between | space-around | space-evenly

align-items — aligns along cross axis (vertical if row): flex-start | flex-end | center | stretch | baseline

align-content — like align-items but for multiple rows (only when wrapping)

gap: 16px — space between items. Can be gap: row-gap col-gap

flex-flow — shorthand for direction + wrap

flex-grow — how much item grows to fill space. 1 = fill available space equally. Default 0.

flex-shrink — how much item shrinks when space is tight. Default 1 (all shrink equally). 0 = never shrink.

flex-basis — initial size before grow/shrink. Default auto (use width).

flex: 1 — shorthand for 1 1 0. Makes item fill space equally with siblings.

flex: 0 0 200px — fixed 200px, no grow, no shrink.

align-self — overrides align-items for this item

order — visual order. Default 0. Lower = earlier. Can be negative.

margin: auto — on flex item, absorbs all available space in that direction. Classic trick: margin-left: auto pushes item to far right.

Grid handles rows AND columns simultaneously. More powerful than flex for full page layouts.

display: grid — activates grid

grid-template-columns: 200px 1fr 2fr — defines column sizes. fr = fraction of remaining space.

grid-template-rows: auto 1fr auto — defines row sizes.

repeat(3, 1fr) — shorthand for 1fr 1fr 1fr

repeat(auto-fit, minmax(200px, 1fr)) — responsive columns. Fills row with as many 200px+ columns as fit. Best trick in CSS.

auto-fill vs auto-fit — auto-fill keeps empty tracks, auto-fit collapses them. Use auto-fit almost always.

grid-template-areas — name regions visually in CSS. Then assign items with grid-area: name.

gap: 16px — space between rows and columns

grid-column: 1 / 3 — span from column line 1 to 3 (spans 2 columns)

grid-column: span 2 — span 2 columns from current position

grid-row: 1 / -1 — span full height. -1 = last line.

grid-area: header — place in named area

justify-items — aligns items horizontally within their cell

align-items — aligns items vertically within their cell

justify-self / align-self — same but per item

place-items: center — shorthand for both. Center everything in cells.

Grid lines start at 1, not 0. Negative lines count from the end.

position: static (default) — normal document flow. top/left/right/bottom have no effect.

position: relative — stays in normal flow but you can offset it with top/left/etc. Its original space is preserved. Also creates a stacking context and becomes the reference point for absolute children.

position: absolute — removed from normal flow. Positioned relative to nearest ancestor with position that isn't static. If none found, relative to initial containing block (viewport). Classic pattern: parent relative, child absolute.

position: fixed — removed from flow. Positioned relative to viewport. Stays put on scroll. Used for navbars, modals.

position: sticky — hybrid. Acts like relative until it hits a scroll threshold, then acts like fixed. Stays within its parent. Used for sticky table headers, section labels.

z-index — controls stack order. Only works on positioned elements (non-static). Higher z-index = on top. Creates a stacking context.

font-family: 'Inter', sans-serif — list fallbacks. Last one should be generic: serif, sans-serif, monospace.

font-size — use rem for accessibility. 1rem = browser default (usually 16px). em is relative to parent font size.

font-weight: 400 | 700 — normal/bold. Or numeric 100-900.

font-style: italic | oblique

line-height: 1.5 — unitless preferred. Relative to font size. 1.4-1.7 for body.

letter-spacing: 0.05em

@font-face — load custom fonts. Most use Google Fonts <link> instead.

text-align: left | center | right | justify

text-decoration: none | underline | line-through

text-transform: uppercase | lowercase | capitalize

text-overflow: ellipsis — shows ... when text overflows. Needs overflow: hidden and white-space: nowrap to work.

white-space: nowrap | pre | pre-wrap — controls wrapping

word-break: break-all — break long words (URLs)

overflow-wrap: break-word — softer version, breaks only when necessary

Multi-line clamp: display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden

Color formats: #hex, rgb(), rgba(), hsl(), hsla(), named colors. Modern: oklch() for perceptually uniform colors.

opacity: 0.5 — affects element AND all children. Use rgba(0,0,0,0.5) or color-mix() if you only want transparent background.

background-color — solid color

background-image: url(...) — image background

background-size: cover | contain | 100% — cover fills area (may crop). contain shows full image (may leave gaps).

background-position: center center

background-repeat: no-repeat | repeat-x

background-attachment: fixed — parallax effect

background — shorthand for all above

currentColor — inherits the element's color value. Useful for SVG icons that should match text color.

px — pixels. Fixed. Use for borders, fine details.

pt, cm, mm — print units. Rarely used in screen CSS.

rem — relative to root font size. Consistent. Best for font sizes and spacing.

em — relative to parent's font size. Compounds. Use carefully.

% — relative to parent dimension.

vw, vh — viewport width/height. 100vh = full screen height.

svh, dvh — small/dynamic viewport height. Fix for mobile browser chrome (URL bar shrinks on scroll). Use dvh for truly full-screen mobile.

ch — width of "0" character. Useful for text inputs (width: 20ch).

fr — grid fraction unit.

Media queries — apply styles at specific conditions:

@media (max-width: 768px) { ... } — mobile-first reversed (desktop-first). Apply below 768px.

@media (min-width: 768px) { ... } — mobile-first (preferred). Apply above 768px.

@media (prefers-color-scheme: dark) — dark mode

@media (prefers-reduced-motion: reduce) — disable animations for users who prefer it

@media print — print styles

Container queries — modern alternative. Respond to parent container size instead of viewport. @container (min-width: 400px) { ... }. Parent needs container-type: inline-size.

Common breakpoints (rough): mobile <480, tablet 480-768, desktop 768-1200, wide >1200. Tailwind uses: sm 640, md 768, lg 1024, xl 1280.

Declare on :root for global scope: --color-primary: #3b82f6;

Use anywhere: color: var(--color-primary);

Fallback value: var(--color-primary, blue) — uses blue if variable not set.

Unlike preprocessor variables (Sass), CSS variables are live in the DOM — you can change them with JS, override per component, and they work with calc().

Scoped to component: declare on a class instead of :root, only children inherit it.

Dark mode pattern: redefine variables inside @media (prefers-color-scheme: dark) or a [data-theme="dark"] attribute. Only the variable values change, all the rules stay the same.

Animate between two states (e.g. hover). Define on the base state, not the hover state.

transition: property duration easing delay

transition: all 0.3s ease — animate all properties

transition: color 0.2s ease, transform 0.3s ease-out — multiple

Easing: ease | ease-in | ease-out | ease-in-out | linear | cubic-bezier()

Avoid transitioning all in production — can animate unintended properties.

Define with @keyframes, apply with animation property.

animation: name duration easing delay iteration direction fill-mode

animation-iteration-count: infinite | 3

animation-direction: normal | reverse | alternate

animation-fill-mode: forwards — keeps final state after animation ends

animation-play-state: paused — pause via CSS or JS

Performance tip: only animate transform and opacity. These are GPU-accelerated. Animating width, height, top, left causes reflows (slow).

Transforms don't affect document flow — the element moves visually but its original space is preserved.

translate(x, y) — move. Use instead of top/left for animations.
scale(1.2) — scale up 20%. scale(0.5) — half size.
rotate(45deg) — rotate clockwise.
skew(10deg) — skew.
matrix() — all transforms as one matrix. Rarely written by hand.

transform-origin: center — point of transformation. Default center. E.g. top left for fold effects.

transform: translateX(-50%) translateY(-50%) — classic centering trick with absolute positioning.

overflow: visible | hidden | scroll | auto

auto — only shows scrollbar when needed. Best choice usually.

hidden — clips content and hides scrollbar. Also creates a new block formatting context (clears floats).

overflow-x / overflow-y — control each axis independently.

scroll-behavior: smooth — smooth scrolling for anchor links. Put on html or the scrolling container.

overscroll-behavior: contain — prevent scroll from propagating to parent. Stops page from scrolling when modal is fully scrolled.

scroll-snap-type: x mandatory — snap scrolling. On container. Items use scroll-snap-align: start.

filter: blur(4px) brightness(0.8) contrast(1.2) grayscale(1) invert(1) sepia(0.5)

backdrop-filter: blur(10px) — blur content behind element. Used for frosted glass UI. Requires transparent background.

mix-blend-mode: multiply | screen | overlay — how element blends with what's behind it.

clip-path: circle(50%) | polygon(...) | inset(...) — clip element to a shape.

object-fit: cover | contain | fill — how img or video fills its box. Like background-size but for replaced elements.

object-position: center top — like background-position for replaced elements.

· margin: auto centers block elements horizontally (with a fixed width). Doesn't center vertically in normal flow.

· % height on an element requires parent to have defined height.

· Flex/grid items ignore float.

· z-index only works on non-static positioned elements.

· Pseudo-elements need content property or they don't appear.

· transition doesn't work on display property (can't fade display:none in). Use opacity + visibility combo or @starting-style.

· Stacking context: any element with position + z-index, opacity < 1, transform, or filter creates a new stacking context. Children z-index only compete within it.

Horizontally center block: margin: 0 auto + fixed width

Horizontally center inline: text-align: center on parent

Center with flex: display:flex; justify-content:center; align-items:center

Center with grid: display:grid; place-items:center

Center absolute element: top:50%; left:50%; transform:translate(-50%,-50%)

Center absolute with new CSS: inset:0; margin:auto + defined width/height

:is(), :where() — simplify selector lists

:has() — parent selector. Finally.

gap on flex — no more margin hacks

aspect-ratio: 16/9 — maintain aspect ratio without padding tricks

logical propertiesmargin-inline-start instead of margin-left for RTL support

@layer — cascade layers. Organize CSS without specificity wars.

color-mix(in srgb, red 50%, blue) — mix colors natively

@starting-style — animate elements entering the DOM (finally!)

Some properties inherit from parent automatically: color, font-*, line-height, letter-spacing, text-align, visibility, cursor

Most don't inherit: margin, padding, border, background, width, height, display, position

inherit — force any property to inherit from parent

initial — reset to browser default

unset — inherit if inheritable, otherwise initial

revert — reset to browser stylesheet value