position: fixed + overflow: hidden + (plus some relative positioning and z-index stuff)

11 Jun 2015

If you have an element with position: fixed inside of an element that has overflow: hidden, what’s the expected rendering when you need to, uh, overflow? Should the inner fixpos element be clipped by its parent or not?

The spec appears to be pretty clear.

Fixed positioning is similar to absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport.

So, according that spec text, the parent element’s overflow shouldn’t have any effect because the fixpos’ parent element is the viewport.

Neat. But how do browsers behave? Open this testcase and have a look:

https://miketaylr.com/bzla/fixed-overflow-1.html

Everything behaves as the spec describes. overflow: hidden on the parent is ignored. High-fives all around.

Now if you throw in both a z-index: 1 (any number will do) and a position: relative on the parent element, things get…different.

https://miketaylr.com/bzla/fixed-overflow-2.html

Same as first testcase (what I would expect): Mobile + Desktop Firefox Mobile Chrome Desktop Edge

Different from first testcase: Mobile + Desktop Safari: fixpos element is clipped by parent (meaning overflow: hidden worked). Mobile + Desktop Opera (Presto): same as Safari Desktop Chrome: if the viewport is smaller than the containing parent, then overflow: hidden on the parent kicks in (resize the browser window to see it). Mobile + Desktop Opera (Blink): same as Chrome

And now, a 3rd testcase which adds user-scalable=no to the meta (viewport) element (the same effect happens if you constrain intial-scale and maximum-scale to 1.

https://miketaylr.com/bzla/fixed-overflow-3.html

The only browser this seems to make a difference in is Chrome on Android, which now clips the child element. I think I discovered this on accident.

So it seems like non-Edge and non-Firefox browsers treat a position: fixed element as a position: absolute element (or something?), when contained by a position: relative parent that also has a z-index set.

Unfortunately at least one site relies on this bug (see this comment).

If you happen to know why, send a self-addressed stamped envelope to twitter dot com slash miketaylr and let me know.

UPDATE

See https://twitter.com/gregwhitworth/status/609095284010852352 from @gregwhitworth. I’ll try to write a follow-up post when I understand everything.