LearnThatStack Ace your next interview

CSS3

CSS in current Chrome, Edge, Firefox and Safari Checked Oct 2026 116 code snippets

The model

  • The cascade picks one value per property, by origin, layer, specificity, then source order. Inheritance fills in what no rule sets.
  • Every element is a box of content, padding, border and margin. With box-sizing: border-box, width includes the padding and border.
  • display sets how a box lays out its children, in normal flow, flex or grid. position: absolute and fixed take a box out of the flow.
  • z-index only compares boxes in the same stacking context. opacity below 1 and transform each start a new one.
Stylecascade picks valuesLayoutsizes the boxesPaintfills in pixelsCompositestacks the layerswidth, top, margincolor, box-shadowtransform, opacity
A change starts the work where its arrow ends, and every step to the right runs too. transform and opacity skip layout and paint, so animate those.

Cascade & selectors

which rule wins, and what it matches

Resets and cascade layers

Match every element*It adds no specificity.
Make every box border-box*, *::before, *::afterbox-sizing: border-box
Choose a reset or normalizeA reset wipes defaults. Normalize keeps them and fixes browser bugs.
Order your layers once@layer base, utilities;A later layer beats any specificity.
Style a component, stopping at an inner part@scope (.card) to (.body)

TrapUnlayered styles beat every layer, unless the layered rule is !important.

Selectors and combinators

Match any descendant, or direct children onlydiv pdiv > p
Match the next sibling, or every later oneh2 + ph2 ~ p
Match an attribute by its start, end or middle[href^="https"][href$=".pdf"][href*="docs"]
Count every sibling, or only the same tag:nth-child(2n):nth-of-type(2)

Trapp:nth-child(2) counts every sibling. After a heading, it matches the first paragraph.

Pseudo-classes and pseudo-elements

Style a state, or a part of an element:hover::before: for a state, :: for a part.
Number items with CSS alonecounter-reset: itemcounter-increment: itemcontent: counter(item)
Style placeholder text::placeholderAdd opacity: 1, since Firefox dims it.
Highlight text without changing the DOM::highlight(hit)

TrapA placeholder is a hint, not a label. It disappears as the user types.

Box model & positioning

how big a box is, and where it sits

Display types and hiding

Tell block, inline and inline-block apartBlock starts a new line. Inline ignores width and height. Inline-block accepts them.
Hide it and close the gap, or keep its spacedisplay: nonevisibility: hidden
Hide text from sight, not from screen readersUse an .sr-only class that clips it to 1px.

Tipopacity: 0 keeps the space and still takes clicks.

Trapdisplay: none and visibility: hidden both hide the element from screen readers too.

Position and stacking

pagecard z:1aside z:2modal z:99
z-indexThe card starts a stacking context. Its z:1 loses to z:2, so z:99 can't lift the modal.
Place a box against a positioned parentposition: absoluteGive the parent position: relative.
Stick a header once it scrolls to the topposition: sticky; top: 0
Fix a huge z-index that has no effectMove the box out of the parent's stacking context.
Tie a tooltip to another elementanchor-name: --tipposition-anchor: --tip
Start a stacking context with no side effectsisolation: isolate

Trapoverflow: hidden on a parent can stop sticky. A transform on an ancestor pins fixed to that ancestor.

Flexbox & Grid

lay out rows, columns and whole pages

Grid tracks and areas

Choose Grid or FlexboxGrid for two dimensions, Flexbox for one.
Fix one column and split the rest 1 to 2grid-template-columns: 200px 1fr 2fr
Draw the layout as named areasgrid-template-areas: "side main"grid-area: main

TrapPercentages ignore gap, so 20% 40% 40% plus a gap overflows. fr shares only what's left.

Center, sticky footer, equal columns

Center a child on both axesdisplay: gridplace-items: center
Center an overlay such as a modaltransform: translate(-50%, -50%)Set top and left to 50% first.

TipFlex and grid items stretch to the tallest in their row, so columns match.

Responsive design

fit any screen, container and image

Viewport and units

Stop phones laying out the page 980px widewidth=device-width, initial-scale=1In the viewport meta tag.
Size text so it follows the user's settingsfont-size: 1.25remem uses the element's own font size.
Fill a phone screen under its toolbarheight: 100dvh100vh can run under it.

TipTo clear a notch, add viewport-fit=cover and pad with env(safe-area-inset-top).

clamp() and math functions

Keep a size between a minimum and a maximumclamp(1rem, 4vw, 2rem)Minimum, preferred, maximum.
Mix units in one valuecalc(100% - 40px)Spaces around + and - are required.
Place items around a circlecalc(cos(45deg) * 100px)

TrapKeep a font's clamp() maximum in rem and at least twice the minimum, or text stops growing when users zoom.

Transitions & animations

change and move things smoothly

Animations and scroll snap

Define the steps of an animationWrite @keyframes with from, to or percentages.
Run it forever, back and forthanimation: pulse 2s infinite alternate
Animate an element as it scrolls into viewanimation-timeline: view()Not in every browser yet.
Make a carousel settle on whole slidesscroll-snap-type: x mandatoryscroll-snap-align: start

TrapWithout animation-fill-mode: forwards, the element snaps back when the animation ends.

Theming, color & effects

variables, dark mode and visual effects

Custom properties and dark mode

Define a variable and read it with a fallback--brand: #07fcolor: var(--brand, black)
Let the browser theme controls and scrollbarscolor-scheme: light darkIt won't change colors you set.
Give one color per scheme in one linelight-dark(#333, #fff)

TrapA plain custom property can't animate smoothly. Register it with @property first.

Forms, print & accessibility

form controls, print and accessible widgets

Accessibility and CSS-only widgets

Show a focus ring to keyboard users:focus-visibleIt skips the ring on mouse clicks.
Cut motion for users who ask for less@media (prefers-reduced-motion: reduce)
Build an accessible accordion<details><summary>
Build one with a hidden checkbox:checked + .panelKeyboard and screen reader users can't open it.
Show a tooltip from a data attributecontent: attr(data-tip)

TrapCSS can't fix missing semantics. Never carry meaning by color alone.

Form controls and validation

Strip a control's native look and fontappearance: nonefont: inherit
Draw your own checkbox:checked + label::beforeHide the input with opacity: 0.
Style a field once the user has left it invalid:user-invalid

Trap:invalid matches an empty required field as soon as the page loads.

Performance

load fast and render cheaply

What a change costs

Animate at 60fpstransformopacityThey skip layout and paint.
Promote an element just before it animateswill-change: transformRemove it after. Each layer costs memory.
Avoid layout thrashingDon't read offsetHeight right after a style change.
Know how a browser matches a selectorRight to left, from the rightmost part up the ancestors.

Trapwill-change creates a stacking context before anything moves, which can change z-index.

Load fast, without layout shifts

Paint the first screen before the stylesheet arrivesInline the critical CSS, then load the rest without blocking.
Ship fewer bytes of CSSPurge unused rules, minify, compress, and split by route.
Show fallback text while a web font loadsfont-display: swapLoad the font with @font-face, as WOFF2.
Stop images shifting the layoutaspect-ratio: 16 / 9This keeps CLS low.
Keep layout and paint work inside a widgetcontain: content

TrapInlined CSS repeats in every page and can't be cached on its own.

Architecture & tooling

keep styles in order as the code grows

BEM, OOCSS and Atomic CSS

Name classes the BEM way.card__title.card--featuredBlock, element, modifier.
Separate structure from skinOOCSS puts layout in one class and colors in another.
Style with one-property utility classesAtomic CSS, as in Tailwind's flex or p-2.
Avoid specificity fights in a big appOne class per selector, plus cascade layers.

Organize CSS at scale

Scope class names to one file at build timecard.module.cssCSS Modules. No runtime cost.
Drive styles from component propsCSS-in-JS. Runtime libraries add work on every render.
Order styles from generic to specificResets first and utilities last, as ITCSS does.
Name every design value once--color-actionSemantic names point at raw values.

Browser support & debugging

ship new CSS safely, and find layout bugs

Feature detection and fallbacks

Use a feature only where it works@supports (display: grid)Add not for the fallback.
Give old browsers a fallback valuePut a safe value first. Browsers skip unknown values.
Choose progressive enhancement or graceful degradationBuild a base that works everywhere, then add to it.

Trap@supports proves the syntax parses, not that the feature works without bugs.

Found this useful? Pass it on.
Pro · $10/mo

This sheet stays free. With Pro, you can:

  • Every answer on this sheet. Read the full answer to all 110 questions it links, not just the 15 free ones.
  • My sheet. The cards you star and the ones you miss in Quiz me, from every sheet, on one page to quiz and print.
  • PDFs. Download this sheet and My sheet, laid out for A4, with every question a link to its answer.
  • The rest of Pro. Every answer in the question library, and 1,000 AI credits a month.