为什么display:inline会影响使用position:sticky的子元素?

3

据我理解,如果带有 position:sticky 属性的元素嵌套在父元素中,当父元素离开视窗时,“粘性”元素也会离开。

在这里,我有一个“粘性”的 <ul> 元素,它位于 <main> 中的 <nav> 中。当通过主要元素滚动时,当 <nav> 通常会滚动到屏幕外时,它的行为与变成 position:sticky 一样。但是,如果我将 <nav>display 更改为 blockinline-block,它的行为就像我最初的想法一样。这是怎么回事?

body {
  border: 2px dotted gray;
  padding: 2rem;
}

nav {
  display: inline;
}

ul {
  top: 0;
  position: sticky;
  width: 100%;
  
  list-style: none;
  padding: 1rem 0;
  display: flex;
  gap: 1rem;
  font-weight: bold;
  border: 2px dotted gray;
  background: white;
}
<body>
  <main>
    <nav>
      <ul>
        <li>one</li>
        <li>two</li>
        <li>three</li>
      </ul>
    </nav>

    <h1>Main Heading</h1>
    <div>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean quis enim ipsum. Quisque vel lacinia urna. Aenean et cursus nisi. Mauris eleifend fermentum elit, id finibus sem varius id. Duis imperdiet massa at velit ultrices gravida id sit amet ipsum. Praesent convallis quis metus nec dignissim. Etiam et odio id odio tincidunt bibendum quis vel urna. Cras ultricies diam eget nisl posuere, vel mollis sapien venenatis. Nulla eu diam hendrerit, gravida dolor vitae, cursus nulla.</p>
      <p>Maecenas vulputate viverra diam elementum volutpat. Sed vulputate ac velit et tincidunt. Mauris eget nisl ut mauris eleifend accumsan. Phasellus accumsan ultricies leo, vitae gravida tellus rutrum sed. Proin condimentum pulvinar rhoncus. Duis quis massa ligula. Cras ac est aliquet, facilisis leo nec, scelerisque arcu. Nunc ultricies sollicitudin semper. Nulla varius laoreet posuere. Suspendisse hendrerit nulla id mi rhoncus iaculis. Donec interdum ultricies risus, eget malesuada justo pellentesque placerat. Cras convallis eget dolor in tempus. Ut imperdiet tellus eu nibh bibendum rutrum.</p>
      <p>Integer eros purus, porta non rhoncus a, accumsan et lectus. Ut a ullamcorper purus. Proin mattis fermentum lorem varius mollis. Nullam imperdiet, neque auctor sodales molestie, nulla enim suscipit leo, id cursus nibh quam vel neque. Curabitur mauris nunc, varius id pharetra sed, elementum nec tellus. Morbi luctus auctor egestas. Cras accumsan arcu ullamcorper porttitor imperdiet. Sed semper magna nec nibh venenatis, sed laoreet neque malesuada. Aenean sit amet erat molestie, efficitur lacus vitae, laoreet lectus. Proin elit enim, ultrices nec nibh eget, vehicula maximus odio. Nunc egestas dapibus porta. Mauris aliquet bibendum ultrices.</p>
      <p>Praesent efficitur sit amet magna bibendum bibendum. In convallis nisl aliquam vulputate gravida. Praesent ornare pretium dapibus. Aliquam malesuada in metus eget eleifend. Morbi at cursus augue, sed sagittis dolor. Pellentesque facilisis urna metus, et maximus risus tristique et. Cras blandit condimentum pulvinar. Fusce mattis egestas tortor, ut aliquam libero ultrices eu. Praesent mauris enim, egestas id tristique in, mollis in tellus. Integer tristique augue quis lorem facilisis, non convallis lorem consequat. Morbi sagittis at mi ac finibus. Vivamus eget diam nec quam lobortis viverra. Morbi viverra ut odio non vehicula.</p>
      <p>Proin faucibus tortor quis nisl placerat, eget commodo ante iaculis. Proin quis aliquam ante, a iaculis nisi. Vivamus porta mi et neque ullamcorper mattis. Suspendisse cursus, urna et placerat posuere, risus arcu tempor nunc, eget hendrerit nulla ex maximus ante. Morbi elit mauris, vestibulum vel elementum et, mattis non quam. Quisque aliquet congue quam, id dictum nunc scelerisque in. Mauris ipsum risus, vestibulum venenatis lorem vitae, porta semper ante. Aliquam eu velit vitae neque iaculis vestibulum id a magna. Integer malesuada at lacus ac vulputate.</p>
    </div>
  </main>
</body>


我不确定你在哪里读到了关于粘性定位的内容,但根据https://www.w3schools.com/css/css_positioning.asp,它似乎是不同的。 - kiner_shah
如果您在包含另一个 div 的 div 中(例如 <div><div class="sticky">I am sticky!</div></div>),将具有类 sticky 的 div 包装起来,则它将停止像 position: sticky 一样运作。然后,如果您向该包装器 div 添加 display:inline,则它将再次表现为 position: sticky,但父级 "包装器 div" 也会随着它在页面上向下移动。只要所有父级都是 display:inline,您可以多次执行此操作,但如果其中任何一个是 display:blockinline-block,则它将停止工作。 - Lovethenakedgun
1个回答

1
这段文字讲述了“包含块”的概念。sticky定位不考虑父元素,而是考虑其包含块,大多数情况下包含块是父元素,但在你的情况中不是,因为:
对于其他元素,如果元素的位置是'relative'或'static',则包含块由最近的祖先框的内容边缘形成,该祖先框是块容器或建立格式化上下文(参见ref)。
其中没有提到'sticky',但它的行为与'relative'和'static'相同(https://www.w3.org/TR/css-position-3/#def-cb)。
如果您查看sticky的定义,可以阅读:
与相对定位类似,但其偏移量会自动根据最近的祖先滚动容器的滚动视口(由内嵌属性修改)在未同时为auto的轴上进行调整,以尝试在用户滚动时将该框保持在其包含块中可见。这种定位方案称为粘性定位。所以在这种情况下,包含块不再是nav而是main。ref

啊,谢谢。我确信我在某个地方读到了“父元素”,并在MDN上发现他们的命名可能会让我困惑。但是,在页面的前面部分声明:“粘性定位元素按照文档的正常流程进行定位,然后相对于其最近的滚动祖先和包含块进行偏移...”,而在页面的后面部分声明:“当一个元素越过指定阈值时,它被视为相对定位,直到它达到其父元素的边界,此时它被视为固定定位”。https://developer.mozilla.org/en-US/docs/Web/CSS/position - Lovethenakedgun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接