如何让设置position:sticky的div保持固定不随后续元素滚动?
问题描述
网页包含3个div,将第二个div设置为position:sticky属性后,预期效果为:滚动页面时第一个div滚出顶部,第二个div到达顶部后固定;第三个div滚动过第二个div并滚出顶部,而第二个div仍保持固定。但实际情况是第三个div到达顶部时,会和第二个div一起滚出顶部。
问题原因
position: sticky元素的粘性定位仅在其父容器的滚动范围内生效。你的第二个div直接作为body的子元素,而body的高度仅由三个div的内容总和决定(约297vh)。当滚动到第三个div的顶部到达视口时,第二个div的文档流位置已经完全处于body的前半部分,超出了粘性生效的范围,因此会跟着一起滚出视口。
解决方案
将第二个div包裹在一个高度足够大的容器中(与html高度一致,设为500vh),让这个容器成为它的滚动父容器,这样第二个div的粘性范围就能覆盖整个页面滚动区域。同时给第二个div设置更高的z-index,避免被第三个div覆盖。
修改后的代码示例
HTML 部分
<head> <link rel='stylesheet' type='text/css' href='style.css' /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script> <script src="javascript.js" type="text/javascript"></script> </head> <body> <div id="checkbox"> <input class="checkboxes" id="divGroup2Sticky" type="checkbox"> <label for="divGroup2Sticky">Div Group 2 Sticky</label> </div> <div id="divGroup1" class="divGroup"> <p>Div Group 1</p> <div class="innerDiv" style="border: solid black 1px"> <div class="innerDiv" style="border: solid yellow 1px"> <div class="innerDiv" style="border: solid brown 1px"> </div> </div> </div> </div> <!-- 新增容器包裹第二个div --> <div class="sticky-container"> <div id="divGroup2" class="divGroup"> <p>Div Group 2</p> <div class="innerDiv" style="border: solid purple 1px"> <div class="innerDiv" style="border: solid orange 1px"> <div class="innerDiv" style="border: solid green 1px"> </div> </div> </div> </div> </div> <div id="divGroup3" class="divGroup"> <p>Div Group 3</p> <div class="innerDiv" style="border: solid turquoise 1px"> <div class="innerDiv" style="border: solid fuchsia 1px"> <div class="innerDiv" style="border: solid maroon 1px"> </div> </div> </div> </div> </body>
CSS 部分
html { height: 500vh; } body { background-color: gray; margin: 0; /* 移除默认margin避免布局偏移 */ } .divGroup { position: relative; margin-top: 1vh; margin-left: 1vh; width: 98vw; height: 98vh; background-color: darkgray; border: solid red 1px; } /* 新增粘性容器样式 */ .sticky-container { height: 500vh; /* 和html高度一致,确保粘性范围覆盖整个页面 */ margin-top: 1vh; /* 保持和其他div一致的间距 */ } #divGroup2 { z-index: 2; /* 确保在第三个div上方 */ margin-top: 0; /* 容器已设置margin,移除自身margin避免重复 */ } .innerDiv { position: absolute; top: 50%; left: 50%; translate: -50% -50%; width: 80%; height: 80%; } p { margin: 0; font-size: 25px; text-align: center; } #checkbox { position: fixed; top: 2vh; left: 2vw; background-color: #D3D3D3; border: 1px solid black; border-radius: 5px; padding: 4px; z-index: 3; }
JavaScript 部分
window.onload = function() { $('#divGroup2Sticky').change(function() { let divName = 'divGroup2' let div = $(`#${divName}`) if (this.checked) { div.css('position', 'sticky') div.css('top', '1vh') div.css('left', 'auto') } else { div.css('position', 'relative') div.css('top', '0px') div.css('left', '0px') } }) }
效果说明
勾选复选框后,第一个div滚出视口时,第二个div会固定在顶部1vh的位置;继续滚动时,第三个div会从第二个div的下方向上滚动并最终滚出视口,而第二个div会一直保持固定状态,直到页面滚动到最底部。
内容的提问来源于stack exchange,提问作者Verticon
相关产品推荐
相关产品推荐

