Technote

Themes & plugins Advanced

Series Layouts that hold up on mobile Part 8 of 8

Why sticky quietly dies — one overflow line on an ancestor

position: sticky throws no error when it fails. Check three things in order — a threshold, room in the parent, an ancestor's overflow — and the cause is almost always there.

This is the last part of the series. So far you have settled the order, taken breakpoints from the content, made sizes fluid, stopped grid tracks from swelling, hunted horizontal overflow, sized things for fingers and sorted out navigation. The finale is position: sticky — a property that eats afternoons precisely because it says nothing when it fails.

Three conditions, checked in order

First, there must be a threshold. Writing position: sticky without any of top or bottom leaves nothing to stick against, so nothing happens. A missing top: 0 is a surprisingly common culprit.

Second, the parent must leave room to travel. A sticky element moves within its parent’s box, not the viewport, and stops at the parent’s bottom edge. If the parent is only as tall as the element itself, the travel distance is zero and nothing appears to stick. Grid and flex hit this constantly, because items stretch to fill the row by default — the sticky element is already full height and cannot move. Give that item align-self: start and its height collapses to its content, restoring the room.

Third, an ancestor’s overflow. This one is the most frequent and the last to be found.

The sticky checklist — the last line alone invalidates the four above it

One ancestor disables the lot

A sticky element sticks relative to its nearest scrolling ancestor. If any ancestor has an overflow value other than visible, that ancestor becomes the scroll container and the element tries to stick inside it. And if that box never scrolls, there is nothing to stick to — so on screen it just looks like an ordinary static element.

This is where the previous part comes back. Add body { overflow-x: hidden; } to paper over horizontal overflow and the vertical axis computes to a scrolling value, at which point every sticky header and sticky table of contents on the site stops at once. The two symptoms usually surface on different pages, which makes the connection genuinely hard to spot.

hidden and clip are not the same

If all you want is to cut content off, there is overflow: clip. It clips but does not create a scroll container, so sticky descendants keep working against the page scroll. For a section that merely trims a decorative background, clip deserves to be your default rather than hidden.

Same goal, different side effects — if you only need clipping, clip is the right word

To find the offender quickly, walk up the ancestors and print the computed values: for (let p = el.parentElement; p; p = p.parentElement) { const s = getComputedStyle(p); if (s.overflow !== 'visible' || s.overflowX !== 'visible' || s.overflowY !== 'visible') console.log(p, s.overflow, s.overflowX, s.overflowY); }

When the sticky header hides your anchors

Once a sticky header works, it brings a companion problem: follow a table-of-contents link and the heading lands behind the header. The fix belongs on the heading — scroll-margin-top.

But do not set that value from a single header-height constant. On narrow screens the header often wraps to two rows and becomes considerably taller, and the desktop value leaves the heading still covered. It reads as “the page scrolled slightly too far” rather than as a fault, which is why it survives review. Measure the real height at each breakpoint and use those values.

Closing the series

One idea ran through all eight parts: rather than finding what broke and adding another breakpoint, build something that does not break. Settle the order narrow, take breakpoints from content, keep sizes fluid, declare your track minimums, hunt overflow per element, size for fingers, decide deliberately what to hide, and know what a single overflow line disables.

To have all of that done on a live site in one pass, there is our optimization program, and the order we work in is published step by step on the process page. Further reading on front-end structure continues in the Themes & plugins archive.

More on this topic

All technotes

Themes & plugins Practical

Decide the editable regions before you design them

A design the CMS cannot express stays up for negotiation long after it ships. Deciding what editors may change, first, removes the negotiation entirely.

Designers 6 min read

₩270,000 · Join the program