Skip to content Skip to sidebar Skip to footer

Why Does Setting `overflow-x: Hidden` On `html` Cause A Child's `position: Sticky` Element To Behave Differently?

The following two example are identical except the first example applies overflow-x: hidden to only the body, while the second example applies it to both html, body. Why does the f

Solution 1:

Here's what the CSS positioning spec has to say about position:sticky

6.2. Sticky positioning

A stickily positioned box is positioned similarly to a relatively positioned box, but the offset is computed with reference to the nearest ancestor with a scrolling box, or the viewport if no ancestor has a scrolling box.

So the matter here is: what is the nearest ancestor with a scrolling box, as opposed what box is scrolled by the vertical scroll bar?

To understand that, we need to take into account overflow propagation. The CSS overflow spec says:

3.4. Overflow Viewport Propagation

UAs must apply the overflow-* values set on the root element to the viewport. However, when the root element is an [HTML] html element (including XML syntax for HTML) whose overflow value is visible (in both axes), and that element has a body element as a child, user agents must instead apply the overflow-* values of the first such child element to the viewport. The element from which the value is propagated must then have a used overflow value of visible.

So, in the first case

body {
  margin: 0;
  overflow-x: hidden;
}

the overflow properties of the body element are propagated to the viewport. Because of that propagation, there's no ancestor element of p.sticky that has a scrolling box, so the sticky offset gets computed relative to the viewport. The viewport is also the box that gets scrolled by the vertical scrollbar.

In the second case,

html, body {
  margin: 0;
  overflow-x: hidden;
}

it's the overflow properties of the html element that get propagated to the viewport, and the body element retains its specified overflow properties, establishing a scrolling box that's the ancestor of p.sticky. The offset is then computed relative to the body element. But it's not the body element that the vertical scrollbar works on, it's still the viewport.

So p.sticky doesn't move relative to the body element, and as the whole thing moves there's nothing for p.sticky to get stuck against.

Post a Comment for "Why Does Setting `overflow-x: Hidden` On `html` Cause A Child's `position: Sticky` Element To Behave Differently?"