我正在尝试创建跟随页面当前部分滚动的内容的浮动预览。用代码解释可能更容易。
我们有当前内容。
<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>
这个过于复杂的解决方案的直觉是使用 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>