← HTML and CSS essentials for modern web developers

Lesson 2 of 4

The box model, specificity and the cascade

2 min read

Box model

Every element is a box: content → padding → border → margin.

css
.card { width: 300px; padding: 20px; border: 1px solid #ddd; }
/* content-box (default): rendered width = 300 + 40 + 2 = 342px */

*, *::before, *::after { box-sizing: border-box; }
/* border-box: rendered width stays 300px; padding and border fit inside */

Almost every modern stylesheet starts with box-sizing: border-box.

Margin collapsing: vertical margins between block elements merge into the larger one (20px + 30px → 30px, not 50px). It doesn't happen inside flex or grid containers.

Display

  • block: full width, starts on a new line (div, p, h1).
  • inline: flows in text; width, height and vertical margins don't apply (span, a).
  • inline-block: flows inline but accepts width and height.
  • none: removed from layout (vs visibility: hidden, which keeps the space).
  • flex / grid: layout modes for children.

Specificity

When rules conflict, the more specific selector wins; on a tie, the later one wins.

SelectorSpecificity (inline, id, class, element)
p0,0,0,1
.card p0,0,1,1
#main .card p0,1,1,1
style="..."1,0,0,0

!important overrides all of it; use it as a last resort. Keep selectors flat (single classes) so styles stay predictable. That's the idea behind BEM (.card__title--active) and utility frameworks like Tailwind.

Positioning

  • static: normal flow (default).
  • relative: normal flow, nudged with top/left; becomes the anchor for absolute children.
  • absolute: removed from flow, positioned against the nearest positioned ancestor.
  • fixed: positioned against the viewport (sticky headers, chat buttons).
  • sticky: normal until it hits a scroll offset, then sticks (table headers, sidebars).

z-index only works on positioned elements (and flex/grid items), and only compares within the same stacking context. That's why a z-index: 9999 modal sometimes still appears behind something.

Units

px fixed; rem relative to the root font size (use for font sizes and spacing so user font settings work); em relative to the element's font size; % relative to the parent; vw/vh relative to the viewport; ch for readable line lengths (max-width: 65ch).

Check yourself

  • What's the rendered width of a 300px box with 20px padding in content-box vs border-box?
  • Which wins: .nav a or #header a?
  • Why might a high z-index not bring an element to the front?

Sign up free to save your progress.