Fix Overlap, Overflow and Z-Index Without Guessing
Diagnose horizontal scroll, stacking contexts and overflow, and fix them with a measured change. After this, you stop raising z-index until something sticks.
Course content
Sign in to save your progress.
-
Layout Without Float Hacks
-
Flexbox for Real Rows and Columns
-
CSS Grid When Flexbox Isn't Enough
-
-
-
Pages That Survive Phones
-
Responsive Layout With Media Queries That Make Sense
-
Mobile-First Without Building Everything Twice
-
Images and Typography That Scale Without Breaking
-
-
-
Components You Can Reuse
-
Navigation That Still Works on a Narrow Screen
-
Cards, Buttons and Shared Styles Across Pages
-
Custom Properties (CSS Variables) You Won't Regret
-
-
-
Forms and States That Look Finished
-
Focus, Hover and Disabled States People Can See
-
Accessible Forms: Labels, Errors and Keyboard Paths
-
-
-
Keep Layouts From Fighting You
-
Fix Overlap, Overflow and Z-Index Without Guessing
-
Organize CSS So You Can Find Things Later
-
-
- Final Check: HTML and CSS Intermediate
Skip ahead: If you already find overflow with DevTools, fix width/min-width instead of raising z-index first, and understand stacking contexts, skip to "Z-index is not a volume knob", then continue.
Horizontal scroll on a phone is almost never "the browser being weird". Something is wider than the viewport. Overlap is a stacking problem. Randomly setting z-index: 9999 treats the symptom and creates the next bug.
Find the wide element
/* temporary diagnostic */
* { outline: 1px solid rgba(3, 75, 255, 0.25); }
Or in DevTools: inspect, watch which box sticks out past the viewport. Common culprits:
- Fixed widths wider than the screen (
width: 1200px) - Negative margins that pull a child out
pre/ long URLs without wrapping- An absolutely positioned badge with a large left offset
img, video, canvas, svg { max-width: 100%; height: auto; }
pre, code { overflow-x: auto; max-width: 100%; }
.page { overflow-x: clip; } /* last resort after fixing the cause */
Prefer fixing the offender. Clipping the page hides the bug until a different element overflows.
Overlap from position
.badge {
position: absolute;
top: -8px;
right: -8px;
}
.card {
position: relative; /* containing block for the badge */
}
position: absolute takes the element out of normal flow. Without a positioned ancestor, it anchors to the initial containing block and can cover unexpected content. Relative on the card is the usual fix for a badge.
Z-index is not a volume knob
z-index only works on positioned elements (and flex/grid children). It compares inside a stacking context. A child with z-index: 9999 cannot escape a parent that created a context with a lower stack level.
Things that create stacking contexts include: opacity less than 1, transform, filter, position with z-index other than auto, and more. If a modal sits under a header, check contexts before inventing larger numbers.
💡 Tip: In Chrome, the Layers panel and the 3D view help, but reading the positioned ancestors in Elements is usually enough.
Common mistakes
z-index: 99999on everything that misbehaves. You lose control of the stack.- Ignoring overflow on a flex/grid child. Add
min-width: 0(ormin-height: 0) so the item may shrink below its content size. - Hiding overflow to "fix" a sticky header covering content. Use
scroll-padding-topinstead.
Flex and grid overflow gotcha
A flex item’s default min-width is auto, which means “as wide as my content”. A long unbreakable string can force the item (and the page) wider than the viewport.
.main {
flex: 1;
min-width: 0; /* allow shrink */
}
The same idea applies to grid items. When a column overflows for “no reason”, check min-width before you invent another media query.
A calm z-index scale
:root {
--z-header: 10;
--z-dropdown: 20;
--z-modal: 30;
}
.site-header { z-index: var(--z-header); }
.modal { z-index: var(--z-modal); }
Named layers beat random five-digit numbers. When two elements fight, you compare roles, not invent larger integers.
What happens if you skip this
Every new sticky widget raises z-index again. Eventually nothing can sit above the header, including the modal that takes payment.
Try it
Force a 1200px-wide child on a phone-sized viewport. Find it in DevTools. Fix the width. Then place a badge with relative/absolute correctly.
When you type another 9 on z-index, what problem are you refusing to name?
About
Diagnose horizontal scroll, stacking contexts and overflow, and fix them with a measured change. After this, you stop raising z-index until something sticks.
- Duration
- 5 min
- Last update
- 08/13/2026
Comments (0)
Sign in to commentNo comments yet.