Why does `overflow:hidden` prevent `position:sticky` from working?

CssCss Position

Css Problem Overview


In the following snippet, there is a sticky div positioned inside a container. It sticks to the top of the scrolling panel while staying inside its container all the time. This is the same behavior as that of the UITableView headers on iOS, where the headers stay visible until the next header is at the top.

In the second snippet, everything is the same except that the container has an overflow:hidden CSS rule. This seems to prevent the position:sticky behavior from working correctly.

.parent {
  position: relative;
  background: #ccc;
  width: 500px;
  height: 150px;
  overflow: auto;
  margin-bottom: 20px;
}

.hidden-overflow {
  overflow: hidden;
}

.sticky {
  position: sticky;
  background: #333;
  text-align: center;
  color: #fff;
  top: 10px;
}

<div class="parent">
  <div>
    <div class="sticky">
      Hi, I am a sticky inside the container which contains the first paragraph.
    </div>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus volutpat sed metus et porttitor. Integer bibendum lacus eget massa ultricies fermentum. Donec cursus magna eu congue posuere. Sed eget ligula quam. Sed laoreet enim sapien, eget volutpat nisl pellentesque vel. Nulla id dolor sed dolor sodales tristique. Curabitur feugiat massa sed massa bibendum semper et ac orci. In imperdiet nibh quis iaculis viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque vestibulum, nunc non volutpat tristique, nisl nisi volutpat nibh, quis pulvinar purus ex nec justo. Sed a cursus turpis. Quisque nulla odio, lacinia quis vestibulum sit amet, elementum laoreet nisi. Etiam aliquet ligula sagittis,
    consectetur ipsum sit amet, sodales augue.
    </p>
  </div>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus volutpat sed metus et porttitor. Integer bibendum lacus eget massa ultricies fermentum. Donec cursus magna eu congue posuere. Sed eget ligula quam. Sed laoreet enim sapien, eget volutpat
    nisl pellentesque vel. Nulla id dolor sed dolor sodales tristique. Curabitur feugiat massa sed massa bibendum semper et ac orci. In imperdiet nibh quis iaculis viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
    himenaeos. Quisque vestibulum, nunc non volutpat tristique, nisl nisi volutpat nibh, quis pulvinar purus ex nec justo. Sed a cursus turpis. Quisque nulla odio, lacinia quis vestibulum sit amet, elementum laoreet nisi. Etiam aliquet ligula sagittis,
    consectetur ipsum sit amet, sodales augue.
  </p>
  <p>
    Integer congue augue a quam tincidunt, vitae dictum sem iaculis. Proin feugiat nibh vitae leo facilisis, eget laoreet augue dictum. Nunc facilisis tempor feugiat. Aenean eget interdum diam. Maecenas non risus iaculis, scelerisque ipsum eu, facilisis urna.
    Integer velit justo, vestibulum vel vulputate vel, bibendum eu lorem. Phasellus viverra nisl a mi pretium eleifend.
  </p>
</div>
<div class="parent">
  <div class="hidden-overflow">
    <div class="sticky">
      Hi, I am another sticky in the container which contains the first paragraph, but my container has overflow:hidden.
    </div>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus volutpat sed metus et porttitor. Integer bibendum lacus eget massa ultricies fermentum. Donec cursus magna eu congue posuere. Sed eget ligula quam. Sed laoreet enim sapien, eget volutpat nisl pellentesque vel. Nulla id dolor sed dolor sodales tristique. Curabitur feugiat massa sed massa bibendum semper et ac orci. In imperdiet nibh quis iaculis viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque vestibulum, nunc non volutpat tristique, nisl nisi volutpat nibh, quis pulvinar purus ex nec justo. Sed a cursus turpis. Quisque nulla odio, lacinia quis vestibulum sit amet, elementum laoreet nisi. Etiam aliquet ligula sagittis,
    consectetur ipsum sit amet, sodales augue.
    </p>
  </div>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus volutpat sed metus et porttitor. Integer bibendum lacus eget massa ultricies fermentum. Donec cursus magna eu congue posuere. Sed eget ligula quam. Sed laoreet enim sapien, eget volutpat
    nisl pellentesque vel. Nulla id dolor sed dolor sodales tristique. Curabitur feugiat massa sed massa bibendum semper et ac orci. In imperdiet nibh quis iaculis viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
    himenaeos. Quisque vestibulum, nunc non volutpat tristique, nisl nisi volutpat nibh, quis pulvinar purus ex nec justo. Sed a cursus turpis. Quisque nulla odio, lacinia quis vestibulum sit amet, elementum laoreet nisi. Etiam aliquet ligula sagittis,
    consectetur ipsum sit amet, sodales augue.
  </p>
  <p>
    Integer congue augue a quam tincidunt, vitae dictum sem iaculis. Proin feugiat nibh vitae leo facilisis, eget laoreet augue dictum. Nunc facilisis tempor feugiat. Aenean eget interdum diam. Maecenas non risus iaculis, scelerisque ipsum eu, facilisis urna.
    Integer velit justo, vestibulum vel vulputate vel, bibendum eu lorem. Phasellus viverra nisl a mi pretium eleifend.
  </p>
</div>

(Snippet adapted from @Daniel's here)

Why doesn't position:sticky work in a container with overflow:hidden?

Css Solutions


Solution 1 - Css

overflow: hidden is not preventing position: sticky from working. But if you set overflow to hidden on any ancestor of your sticky element, then this ancestor element will be the scrolling container for your sticky element. If you switch the overflow value on your ancestor from hidden to scroll and scroll this ancestor (not the window), then you can see that sticky is still working.

See also https://github.com/wilddeer/stickyfill#pro-tips: > Any non-default value (not visible) for overflow, overflow-x, or > overflow-y on any of the predecessor elements anchors the sticky to > the overflow context of that predecessor. Simply speaking, scrolling > the predecessor will cause the sticky to stick, scrolling the window > will not. This is expected with overflow: auto and overflow: scroll, > but often causes problems and confusion with overflow: hidden.

Or http://www.coreyford.name/files/position-sticky-presentation/: > The box's position depends on its containing block (established as for > position:static) as well as its scrolling container, defined by the > nearest ancestor in the same document with a computed value for > 'overflow-x' or 'overflow-y' other than 'visible', or the viewport if > no such ancestor exists.

Or the CSS Positioned Layout Module Level 3 W3C Working Draft:

> 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.

Solution 2 - Css

It's been a few years since this question was originally posted, now there is another way to hide overflowing content:

contain: paint;

https://developer.mozilla.org/en-US/docs/Web/CSS/contain

Solution 3 - Css

I'm not sure this will work in all cases but I've run up against this and was able to get around the issue by replacing overflow: hidden; with clip-paths.

.parent {
    /*overflow: hidden; removed */
    position: absolute; /*this is required for clip-paths to work*/
    -webkit-clip-path: inset(0); /* safari*/
    clip-path: inset(0);
    clip: rect(0px, auto, auto, 0px); /* IE11/Edge (not that IE11 supports sticky anyway!) */
}

As far as having to add position absolute, wrapping the overflow:hidden element in another position: relative element and then adding top, bottom, left and right: 0; should make it fill it's parent container.

Solution 4 - Css

According to Mozilla ( link here )

Sticky is an experimental API and should not be used in production code.

So for me, this alone is the reason why it is not working. Both Edge and IE 11 dont support it either so for me, doing something like this with javascript would be the way forward, there is plenty out there that should help.

An example being this here

Hope this helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncheesusView Question on Stackoverflow
Solution 1 - CsschaenuView Answer on Stackoverflow
Solution 2 - CssseahorsepipView Answer on Stackoverflow
Solution 3 - CssmarmiteView Answer on Stackoverflow
Solution 4 - CssSanspoofView Answer on Stackoverflow