为什么“溢出: 隐藏”会阻止“位置: 粘性”的工作?

在下面的代码片段中,有一个定位在容器内的粘性 div。它粘在滚动面板的顶部,同时一直呆在容器内。这与 iOS 上的 UITableView头文件的行为相同,其中的头文件保持可见,直到下一个头文件位于顶部。

在第二个代码片段中,除了容器有一个 overflow:hidden CSS 规则之外,所有内容都是相同的。这似乎阻止了 position:sticky行为的正确工作。

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

(片段改编自@Daniel’s 给你)

为什么 position:sticky不能在带有 overflow:hidden的容器中工作?

40238 次浏览

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.

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.

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.

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

I ran into this issue and found an alternative solution, to use overflow: clip instead of overflow: hidden. As far as I can tell they work in almost the same way, except the anchor point of the sticky element is unaffected when using clip. The only problem is that as of Nov 2022 overflow: clip has limited (~80%) browser support: https://caniuse.com/mdn-css_properties_overflow_clip