CSS 位置粘性以预览下一个 div 的内容

问题描述 投票:0回答:1

我正在尝试创建跟随页面当前部分滚动的内容的浮动预览。用代码解释可能更容易。

我们有当前内容。

<div class="current-content">
  <p>hi 1</p>
    <p>hi 2</p>
    <p>hi 3</p>
    <p>hi 4</p>
    <p>hi 5</p>
    <p>hi 6</p>
    <p>hi 7</p>
    <p>hi 8</p>
    <p>hi 9</p>
</div>

之后我们还有更多内容。

<div class="next-content">
  <p>hi 1</p>
    <p>hi 2</p>
    <p>hi 3</p>
    <p>hi 4</p>
    <p>hi 5</p>
    <p>hi 6</p>
    <p>hi 7</p>
    <p>hi 8</p>
    <p>hi 9</p>
</div>

这个想法是,当我们从顶部滚动页面时,我们滚动当前内容,但下一个内容使用粘性位置占据视口的 50%,直到它滚动到视图中。

p {
  font-size: 28px;
  marin: 20px;
}

.current-content {
  background: yellow;
}

.next-content {
  background: pink;
  position: sticky;
  bottom: -50vh;
}

问题是,使用 top 似乎不可能实现这一点,因为下一个内容出现在 HTML 树中的当前内容之后。因此只能使用底部来完成。问题是,底部是对下一个内容相对于视口的底部位置的引用,因此如果不知道下一个内容的高度,就无法使其在卡住时仅填充视口的 50%。

我希望这是有道理的,有没有办法实现这一点。

对于上下文,想象一个新闻网站,您可以直接从一篇文章滚动到下一篇文章,但在滚动时,始终会预览下一篇文章的内容,一旦您到达那里,就会滚动到视图中。

p {
  font-size: 28px;
  marin: 20px;
}

.current-content {
  background: yellow;
}

.next-content {
  background: pink;
  position: sticky;
  bottom: -100%; // set to -100% for demonstration purposes
}
<body>
  <div class="current-content">
    <p>hi 1</p>
    <p>hi 2</p>
    <p>hi 3</p>
    <p>hi 4</p>
    <p>hi 5</p>
    <p>hi 6</p>
    <p>hi 7</p>
    <p>hi 8</p>
    <p>hi 9</p>
  </div>
  <div class="next-content">
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
  </div>
</body>

html css sticky
1个回答
0
投票

这个过于复杂的解决方案的直觉是使用 make

current-content
本身 50vh 并允许
overflow:scroll
。这样下一个div就会自然地放在中间了

p {
  font-size: 28px;
  margin: 20px;
}

.current-content {
  background: yellow;
  position: relative;
  height: 50vh;
  overflow: auto;
}

.next-content {
  background: pink;
}
<div class="current-content">
  <p>start1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 1</p>
  <p>hi 2</p>
  <p>hi 3</p>
  <p>hi 4</p>
  <p>hi 5</p>
  <p>hi 6</p>
  <p>hi 7</p>
  <p>hi 8</p>
  <p style="margin-bottom: 0px;">end1</p>
</div>
<div class="next-content">
  <p style="margin-top: 0px;">start2</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>hi</p>
  <p>end2</p>
</div>

但是,正如您所看到的,这不是所希望的,因为它将为

current-content
和父容器创建两个滚动条。

这个想法是使用

animation-timeline:scroll(y)
来检测是否到达
next-content
div 并且应该开始滚动。在
current-content
中创建了覆盖父容器的伪元素,无论用户滚动到哪里,
current-content
容器都会滚动。当它到达末尾时,父容器的滚动条就可以移动,这使得
next-content
位于伪元素上方,这样
next-content
就可以向下滚动。

但是,该解决方案有一个主要限制:由于该解决方案会导致屏幕上半部分出现额外的滚动条,因此通常会选择隐藏它。

p {
  font-size: 28px;
  margin: 20px;
}


/*Not required but since there are childs using z-index, I would wrap it under a new stacking context*/
.wrapper {
  isolation: isolate;
}

.current-content {
  background: yellow;
  padding-bottom: 50vh;
  position: relative;
  height: 50vh;
  width: 100%;
  overflow: auto;
  scrollbar-width: none;
}

.content-wrapper {
  position: relative;
}

.content-wrapper::after {
  content: "";
  position: absolute;
  height: 100%;
  width: 100%;
  z-index: 2;
  display: block;
  top: 50vh;
}

.next-content {
  background: pink;
  position: relative;
  top: -50vh;
  box-sizing: content-box;
  background-clip: content-box;
  animation: offset-next 1ms linear both;
  animation-timeline: scroll(y);
}

@keyframes offset-next {
  from {
    z-index: 1;
  }
  0.01% {
    padding-top: 50vh;
    top: -100vh;
    z-index: 3;
  }
  to {
    padding-top: 50vh;
    top: -100vh;
    z-index: 3;
  }
}
<div class=wrapper>
  <div class="current-content">
    <div class="content-wrapper">
      <p>start1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 1</p>
      <p>hi 2</p>
      <p>hi 3</p>
      <p>hi 4</p>
      <p>hi 5</p>
      <p>hi 6</p>
      <p>hi 7</p>
      <p>hi 8</p>
      <p style="margin-bottom: 0px">end1</p>
    </div>
  </div>
  <div class="next-content">
    <p style="margin-top: 0px">start2</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>end2</p>
  </div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.