如何使一个粘性的div漂浮在页面的其余部分上方?

4

我有一个浮动菜单,固定在窗口顶部,仅占用其宽度的1/4。其余3/4(以及菜单1/4后面)应该由下一个文档部分的图像占用。然而,图像最初出现在菜单下方,即菜单不像我想要的那样浮动。

我得到的结果:

problem

我想要什么:

solution

body,ul {
  margin: 0;
  overflow-x:hidden;
}
header {
  background: green;
}
nav {
  background: #ff000080;
  width: 25vw;
  position: sticky;
  top: 0;
}
main img {
  width: 100vw;
}
<header>Title</header>
<nav>
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
  </ul>
</nav>
<main>
  <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' />
</main>

如何让粘性元素始终浮动,即在其右侧不显示白色空间?
编辑:图片不能在背景上。它应该在main标签内部,那里会有更多的元素,包括文本和可能的其他图像。所有内容都应该一起滚动,除了菜单,必须固定在顶部。

粘性定位和固定定位的区别在于,粘性定位会粘附在当前位置,而固定定位则始终保持不变。为了实现您想要的效果,您需要进行固定定位,并添加一个顶部值,该值等于您的页眉高度。如果您设置了页眉的静态高度,则可以在不使用任何JavaScript的情况下实现此目标。 - THE AMAZING
@THEAMAZING 请阅读我对Prajwal答案的评论。对于这种方法,我需要JavaScript,因为标题不固定,因此在滚动时其可见高度会发生变化。 - Rodrigo
7个回答

3
你可以考虑使用浮动和shape-outside技巧,以确保元素不占用空间:

body,ul {
  margin: 0;
  overflow-x:hidden;
}
header {
  background: green;
}
nav {
  background: #ff000080;
  width: 25vw;
  position: sticky;
  top: 0;
  float:left;
  shape-outside:linear-gradient(transparent,transparent);
}
main img {
  width: 100%;
}
<header>Title</header>
<nav>
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
  </ul>
</nav>
<main>
  <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' />
</main>

另一个想法是考虑使用 height:0 包装器

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

header {
  background: green;
}

nav {
  background: #ff000080;
  width: 25vw;
}

.nav {
  position: sticky;
  top: 0;
  float: left;
  height:0;
}

main img {
  width: 100%;
}
<header>Title</header>
<div class="nav">
  <nav>
    <ul>
      <li>link 1</li>
      <li>link 2</li>
      <li>link 3</li>
    </ul>
  </nav>
</div>
<main>
  <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' />
</main>


@Rodrigo,你能给我展示一下那个空间的截图吗?我看不到任何空间。 - Temani Afif
@Rodrigo 请再检查一下,你可能是在使用Firefox进行测试。更新shape-outside的值,以便其在Firefox上正常工作。 - Temani Afif
谢谢,现在它可以工作了。是的,我正在使用Firefox。在这种情况下,它不是遵循W3C规范吗? - Rodrigo
还是Chrome/Chromium没有遵循W3C规范? - Rodrigo
@Rodrigo 这里并不是关于规范的问题,而是关于使用 100% 的问题... 正确的值是我现在使用的这个。之前我使用的是 100% 而不是 0 0 100% 0,后者等同于 100% 100% 100% 100%,可能会导致意外的结果。 - Temani Afif
显示剩余10条评论

2
我不确定是否可以使用position:sticky实现。因为在没有滚动的情况下,sticky应该与static定位的元素一起分配。
我猜你需要使用JS自己来做这件事。你可以通过优化它的隐藏方式,并使用适当的过渡效果来解决问题。
这是来自MDN的内容:

该元素根据文档的正常流进行定位,然后相对于其最近的滚动祖先和包含块(最近的块级祖先,包括表格相关元素)进行偏移,基于top、right、bottom和left的值。该偏移不会影响任何其他元素的位置。

https://developer.mozilla.org/en-US/docs/Web/CSS/position#sticky

.

.

window.addEventListener('scroll', function(e) {
  if (window.scrollY > 25) {
    document.querySelector('nav').classList.add('sticky');
  } else {
    document.querySelector('nav').classList.remove('sticky');
  }
});
body,
ul {
  margin: 0;
  overflow-x: hidden;
}

header {
  background: green;
}

nav {
  background: #ff000080;
  width: 25vw;
  position: fixed;
}

nav.sticky {
  top: 0;
}

main img {
  height: 100vw;
}
<header>Title</header>

<nav>
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
  </ul>
</nav>

<main>
  <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' />
</main>


几乎可以工作了,除了菜单应该在第25像素的滚动中跟随标题。 - Rodrigo
@Rodrigo 你可以根据 scrollY 手动添加导航栏的 top 位置。 - Prajwal
是的,它可以工作。然而,MDN本身建议不要这样做:这种持续移动和捕捉会导致抖动的视觉效果。一种实现此目的而无需滚动事件侦听器的方法是使用专为此目的设计的CSS属性。我会等待看看是否出现了纯CSS解决方案。 - Rodrigo
@Rodrigo 更好的方法是稍后推送标题位以及导航状态更改。这样,您就可以避免多次绘制。 - Prajwal
我不明白你的意思。 - Rodrigo

1
你可以使用背景CSS属性。你可以在图像标签中使用绝对定位,或者如果你的意图是将图像用作背景,则考虑使用背景属性,下面我粘贴了一个示例代码来使用背景图像和链接到背景属性用法。

https://www.w3schools.com/cssref/css3_pr_background.asp

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

header {
  background: green;
}

nav {
  background: #ff000080;
  width: 25vw;
  position: sticky;
  top: 0;
}

main img {
position: relative;
z-index: -1;
top: -55px;
}
   <header>Title</header>
  
<nav>
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
  </ul>
</nav>
<main>
<img src="https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg" />
</main>
<p>
This is a sample text
</p>


实际上,该图像是页面的一部分。在图像下方将有一些文本,并且当滚动以阅读所有内容时,图像应消失到页面顶部。 - Rodrigo
我已经更新了我的代码片段,请检查一下。这可能不是一个实际的解决方案,但也许可以给你一些想法,尝试调整位置属性。希望这能帮助到你的问题。 - Purushothaman
这种方式需要事先知道<nav>的高度。如果用户更改字体大小(放大或缩小),它可能会破坏布局。 - Rodrigo

0

body,ul {
  margin: 0;
  overflow-x:hidden;
}
header {
  background: green;
  /* changes */
  height: 5vh;
}
nav {
  background: #ff000080;
  width: 25vw;
  /* later changes*/
  position: fixed;
  top: 5vh;
}
main img {
  width: 100vw;
  /* changes */
  position: absolute;
  top: 5vh;
  z-index: -1;
}
<header>Title</header>
<nav>
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
  </ul>
</nav>
<main>
  <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' />
</main>


菜单应该固定在顶部。 - Rodrigo

0

首先,您可以将图像位置设置为position:absolute;,然后将其移动到所需位置。

由于该项目不再粘附,因此我们可以创建一个空的div元素。 还可以在导航之前放置图像(也可以在CSS中使用z-index属性)。

body,ul {
  margin: 0;
  overflow-x:hidden;
}
header {
  background: green;
}
nav {
  background: #ff000080;
  width: 25vw;
  position: sticky;
  top : 0;
}
main img {
  width: 100vw;
  height : 300px;
  /* add z-index */
  z-index : -1;
  /* change position */
  position : absolute;
  top : 20px;
}
<header>Title</header>

<nav>
  <ul>
    <li>link 1</li>
    <li>link 2</li>
    <li>link 3</li>
  </ul>
</nav>
<main>
  <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' />
<!-- create new div to replace image -->
<div style = "width : 100vw; height : 300px;">
</div>
<span> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </span>
</main>


  1. 图像高度不应该被指定,以免拉伸它。
  2. 我在图像后面添加了一些段落到<main>中,但是看不到它们。
- Rodrigo
高度设置仅用于显示滚动条。由于图像位置现在是绝对的,因此在图像之后添加的任何项目必须放在div之后。此外,将div的高度设置为图像的高度。 - Bingostew
如果您绝对需要向<main>添加元素,我已经编辑了代码片段,将div添加到<main>中,并将图像的z-index设置为-1。 - Bingostew

0
  1. 你可以使用z-index来控制img和nav的层级
  2. 或者,你可以创建一个类似于我创建的带有opacity:0;的div来模拟溢出效果

这可能会有所帮助

编辑:

  1. 将img的position设置为relative,因为你想要一个img触发器
  2. 我已经设置了你元素的id DOM名称
  3. 我已经计算出你的nav高度为65,我会自动调整img的top位置
  4. 请不要评判我,我只是想帮忙。
  5. 谢谢

  function SetTop() {
   
    var a = document.getElementById("nav").offsetHeight;
    var b = document.getElementById("img");
    // this 0 because top of img overlapping the "sticky position"
    b.setAttribute("style", "top : "+(0-a)+"px");
  }
body,ul {
  margin: 0;
  overflow-x:hidden;
}
header {
  background: green;
/* you need height for position top of img */
}
nav {
  background: #ff000080;
  width: 25vw;
  position: sticky;
  top: 0;

z-index: 1;
}
main img {
  /* this top need a height from a header */
  top: 0;
  position: relative;
  width: 100vw;
  z-index: -1;
  
}
   
div {
 color: black;
 }
 <body onload="SetTop()"/>
  <header>Title</header>
    <nav id="nav">
     <ul>
       <li>link 1</li>
       <li>link 2</li>
       <li>link 3</li>
     </ul>
    </nav>
  <main>
    <img src='https://cdn.britannica.com/90/3890-050-F451C580/rainforest-coast-lowland-rainforests-Ecuador-tropics-evergreen.jpg' id="img" />
  </main>

   <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  </div>

 </body>


文本应该放在图片下面,而不是覆盖在上面。 - Rodrigo
这个“sticky”需要一个元素,其中{position: relative;} 或除了 absolute 触发。如果你想要一个 <img> 作为一个触发器,你可以改变 <img> {position: relative} 然后把 <img> 的 top 值设置成等于 <nav> 的高度,这需要 script.js 来计算你的 <nav> 的高度..但我会尝试。 - Anonymouse Lovecat

-1

只需在 CSS 中使用 position: sticky; 即可使 div 粘性定位。


如果你读了我的CSS,你会发现我已经在做那个了。 - Rodrigo
他已经将位置设置为“sticky”。您可以尝试使用他添加的代码片段(只需单击“复制片段到答案”),看看是否能够找到解决方案。 - Prajwal

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