Every bug in this lesson has already been explained mechanically somewhere earlier in this domain — this is the field-reference version, the shape each one actually takes in real code, so it's recognizable on sight instead of requiring the mechanism to be re-derived from scratch every time.
3 min read
.paragraph { margin-bottom: 20px; }
.paragraph + .paragraph { margin-top: 30px; }
/* Actual gap: 30px (the LARGER of the two), not 50px — adjacent vertical margins collapse */Covered mechanically in the box-model lesson: adjacent vertical margins on block-level elements merge into a single margin equal to the larger of the two, never adding together. The fix: when a precise, additive gap is actually needed, use gap on a flex/grid container (which never collapses) instead of relying on adjacent margins.
.sidebar { width: 250px; padding: 20px; border: 1px solid #ccc; }
/* Actual rendered width: 250 + 20*2 + 1*2 = 292px, not 250px */Covered mechanically in the box-model lesson: content-box (the default) adds padding and border on top of the declared width instead of including them. The fix: box-sizing: border-box globally, so declared width is always the total rendered width.
.parent { position: relative; z-index: 1; }
.child { position: absolute; z-index: 9999; } /* still loses to an UNRELATED sibling with z-index: 2 */Covered mechanically in the stacking-context lesson: z-index only compares within the same stacking context, and .parent's own z-index: 1 traps .child's 9999 inside it, comparing only against .parent's own siblings. The fix: raising the number never helps a trapped value — find and address the ancestor creating the unwanted stacking context instead.
:focus { outline: none; } /* removes the ONLY visual indicator keyboard-only users have */Covered mechanically in the accessibility lesson: this is a genuinely common, genuinely damaging mistake, since a removed focus indicator makes every interactive element unusable for keyboard-only navigation. The fix: :focus-visible with a real, styled-but-visible indicator, which shows for keyboard nav specifically while suppressing the unwanted mouse-click outline.
elements.forEach((el) => {
el.style.width = box.offsetWidth + "px"; // read, then write, on EVERY iteration
});Covered mechanically in the CSS-performance lesson: reading a layout-dependent property forces a synchronous layout recalculation, and interleaving reads with writes in a loop forces this on every single iteration. The fix: batch all reads first, then batch all writes — one layout pass for the whole operation instead of one per element.
.card:hover { width: 320px; margin-left: -10px; } /* triggers LAYOUT on every animation frame */Covered mechanically in the transitions-and-animations lesson: width/margin are layout-triggering properties, expensive to recompute on every single frame of an animation. The fix: achieve the same visual result with transform: scale() or translate(), which the GPU compositor handles far more cheaply.
Every one of these traces back to the same handful of mechanisms this domain already covered in depth: the box model's precise layer-by-layer measurement rules, the cascade's context-scoped comparisons (stacking contexts included), and the rendering pipeline's three stages with genuinely different costs. Recognizing a bug's shape on sight — "this smells like margin collapsing," "this smells like a trapped stacking context" — is what separates fixing a CSS layout issue quickly from re-deriving these mechanisms from first principles every single time one shows up.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. Why does a sidebar with `width: 250px; padding: 20px; border: 1px solid` render at 292px, not 250px?
2. Why does raising a trapped z-index to an extremely high value never fix a layering bug?
3. What's the actual throughline connecting all six bugs in this field-reference lesson?
CSS & Modern Styling