# Common Layout Bugs and How to Fix Them

The seven layout bugs almost everyone meets, from a page that scrolls sideways to a z-index that won't work, each with its symptom, its cause and the fix that removes the cause instead of hiding it.

Journeyman · CSS · Web Development · Updated November 1, 2026

## After this lesson you can

- Find and fix the element that makes a page scroll sideways, and keep pictures inside their boxes
- Recognize margin collapsing, a flex item that won't shrink and 100vh on phones, and fix each one
- Explain why a sticky header won't stick or a z-index won't work, and fix it at its cause

## Key takeaways

- A page that scrolls sideways has one element wider than the screen. Find it and limit its width, instead of hiding the scroll with overflow-x hidden.
- img { max-width: 100%; height: auto; } keeps a picture inside its box and keeps its shape.
- A flex item won't shrink below its content until you give it min-width: 0.
- On phones, 100vh is the height with the address bar hidden. 100dvh follows the screen as the bar comes and goes.
- A sticky header needs a top value and no ancestor with overflow hidden, auto or scroll. A z-index loses when the group it sits in, its stacking context, is lower.

Search the web for "CSS not working", and the same handful of problems come up again and again: the page slides sideways on a phone, a photo hangs out of its card, the sticky header scrolls away, the menu opens behind the big picture under it. They look like seven different mysteries, and each one has a cause you can name and a fix of a line or two. Learn them once, and the next time a page breaks, at work, in a class project or on your own site, you'll recognize it on sight.

All seven are on Weekend Kitchen's *Slow Sunday Shakshuka* post. For each, here's the symptom, the cause, how to see it with the developer tools, and the fix.

## A page that scrolls sideways

**The symptom:** on a phone, the whole page slides left and right, and there's empty space down the right side.

**The cause:** one element is wider than the screen. It's usually a fixed width (`width: 640px`), a picture, `width: 100vw` (which counts the scrollbar on a computer that shows one, so it's a little too wide), or a long link with no spaces to break at. The outline trick from *Debugging Layouts with Developer Tools* finds it: the box whose red line runs past the edge.

On the shakshuka post, it's the shopping list. You won't see that page slide, though: someone hid the sideways scroll (see the sticky header below), so what's left is a shopping list cut off at the right edge. The fix is the same:

```css
.shopping-list {
  max-width: 640px;
}

.post-source a {
  overflow-wrap: break-word;
}
```

It said `width: 640px`. `max-width` lets it be 640 pixels on a wide screen and narrower on a phone. `overflow-wrap: break-word` lets a long link break onto the next line.

A common quick fix is `overflow-x: hidden` on the body or a wrapper. It hides the scroll, but the wide element is still too wide: its edge is cut off, and on a wrapper it stops a sticky header from sticking (below). Fix the element instead. If you ever do need to cut off something wider than the page, `overflow-x: clip` hides it without those side effects.

## Pictures that spill out

**The symptom:** a photo hangs out past the edge of its card or column.

**The cause:** a picture shows at its own size unless CSS says otherwise. A photo 1200 pixels wide is 1200 pixels wide, inside a card of 340.

```css
img {
  max-width: 100%;
  height: auto;
  display: block;
}
```

`max-width: 100%` says "never wider than your box". `height: auto` keeps the photo's shape: without it, a picture with a `height` attribute in its HTML keeps that height and gets squashed. `display: block` removes the thin gap that appears under a picture, which is there because a picture sits on a line of text, like a letter, by default. Many stylesheets start with this rule for every picture.

![The shakshuka photo hanging out past the right edge of its card, and the same photo after the fix, filling the card's width with its shape kept](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/7c5c1223a9de4746a25f23925075547b.webp)

## Margins that collapse

**The symptom:** a gap is smaller than you added up, or a heading's top margin pokes out above the box it's in, so the box's background starts below a strip of empty space.

**The cause:** **margin collapsing**. When two top and bottom margins touch, the browser keeps only the larger one. A heading's top margin can also pass through the top of its parent and collapse with the parent's own margin, when nothing (no padding, no border) separates them. *Margin, Padding and Border in Practice* first showed this.

The post's *Cook's tip* box has a pale yellow background, but its heading's margin sits above it:

```css
.cooks-tip {
  background-color: #fdf3d0;
  padding: 1rem;
}
```

Padding on the box puts something between the heading's margin and the box's edge, so the margin stays inside. `display: flow-root` on the box does the same without adding padding. In a flex or grid container, margins never collapse, which is one more reason to space items with `gap`. In the box model diagram, a margin that collapses shows its full size, so compare it with the space you see.

## A flex item that won't shrink

**The symptom:** in a row laid out with flexbox, a long title pushes a button out of its box, even though the title is meant to be cut off with "…".

**The cause:** a **flex item** won't shrink below the size of its content, unless you tell it it may. A line of text that isn't allowed to wrap is as wide as the whole line. Here, the text sits in a `<div>` that is the flex item:

```css
.recipe-bar__text {
  min-width: 0;
}

.recipe-bar__title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
```

`min-width: 0` lets the flex item shrink as small as the row needs, so the title is cut off with "…" and the *Print* button comes back. *Flexbox Sizing: flex-grow, flex-shrink and flex-basis* explains why. The same thing happens to grid items in a `1fr` column; the same fix works there.

## 100vh on phones

**The symptom:** a section meant to fill the phone's screen is a little too tall. Its bottom edge, and the *Scroll for the recipe* arrow on it, sit hidden behind the browser's toolbar.

**The cause:** on a phone, the address bar and toolbar slide away as you scroll, so the screen's height changes. `100vh` means the height with the bars hidden, the tallest the screen gets. When the bars are showing, the section is taller than what you can see.

```css
.post-hero {
  min-height: 100vh;
  min-height: 100dvh;
}
```

`dvh` is the **dynamic viewport height**: `100dvh` follows the visible screen as the bars come and go. (`svh` is the height with the bars showing, and `lvh` with them hidden.) The `100vh` line comes first, for older browsers: one that doesn't understand `dvh` skips that line and keeps `100vh`. The next lesson, *Will It Work Everywhere? Browser Support and @supports*, explains that kind of fallback.

## A sticky header that won't stick

**The symptom:** the header has `position: sticky`, and it scrolls away with the page anyway.

**The cause:** one of three things. Check them in order:

1. **No `top` value.** Sticky needs to know where to stick: `top: 0`.
2. **An ancestor with `overflow` set to `hidden`, `auto` or `scroll`.** That ancestor becomes the box the header sticks inside, and it doesn't scroll, so the header never moves. Inspect each element around the header and look for `overflow` in the Computed pane.
3. **A parent no taller than the header.** A sticky element sticks only while its parent is on screen. If the header is wrapped in a `<div>` of its own, there's no room to stick.

Weekend Kitchen had the second cause. Someone hid the sideways scroll with a rule on the `.page` wrapper, which holds the whole page, header included:

```css
/* This hid the sideways scroll, and stopped the header from sticking */
.page {
  overflow-x: hidden;
}
```

Once the shopping list fits the screen (above), delete that rule, and the header's own `position: sticky; top: 0;` works as written. Nothing was wrong with the header at all: the cause was two levels up, which is why checking each ancestor in the Computed pane pays off.

## A z-index that won't work

**The symptom:** the *Recipes* menu opens behind the big photo at the top of the post, the hero. Its `z-index` is `9999`, and it still loses.

**The cause:** one of two things:

1. **The element isn't positioned.** `z-index` does nothing on an element with `position: static`, unless it's a flex or grid item. The developer tools show the `z-index` dimmed, with an **i** that says so.
2. **It's trapped in a stacking context.** A **stacking context** is a group whose layers stack together, like papers in a folder: a z-index only competes inside its own folder. The sticky header starts one (any sticky element does), with `z-index: 1`. The hero has `z-index: 2`. The menu's 9999 only puts it on top of the other things inside the header; the whole header, menu included, is still under the hero.

The fix is at the level of the folders, not the menu:

```css
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
}
```

Now the header's folder is above the hero's, and the menu inside it comes along. The menu's 9999 can go back to a small number. *Stacking: z-index and What Sits on Top* lists everything that starts a stacking context, including `opacity` below 1 and `transform`.

**Try it.** Build a sticky header with a menu inside it, and a hero after it with `position: relative` and `z-index: 2`. Open the menu, watch it hide, then raise the header's `z-index`.

## Check yourself

2 questions to try on the lesson page.

## So what

Each of these bugs looks mysterious until you know its name. Fix the cause, not the symptom: a hidden scroll or a z-index of 9999 is a sign that the real problem is still there.

## Key terms

- [Overflow](https://www.ask-codey.com/glossary/overflow)
- [Margin collapsing](https://www.ask-codey.com/glossary/margin-collapsing)
- [Stacking context](https://www.ask-codey.com/glossary/stacking-context)
- [Sticky positioning](https://www.ask-codey.com/glossary/sticky-positioning)
- [Viewport](https://www.ask-codey.com/glossary/viewport)

## Cheat sheets

- [Common Layout Bugs and How to Fix Them](https://www.ask-codey.com/cheat-sheets/css-common-layout-bugs-cheat-sheet)

## Related

- [Debugging Layouts with Developer Tools](https://www.ask-codey.com/lessons/css-debugging-with-devtools)
- [Positioning: fixed and sticky](https://www.ask-codey.com/lessons/css-position-fixed-and-sticky)
- [Stacking: z-index and What Sits on Top](https://www.ask-codey.com/lessons/css-z-index-and-stacking)
- [Flexbox Sizing: flex-grow, flex-shrink and flex-basis](https://www.ask-codey.com/lessons/css-flexbox-sizing)

Source: https://www.ask-codey.com/lessons/css-common-layout-bugs
