如何用 CSS 实现文字滚过全屏粘性图片的效果?
数据阿明
实现思路
可以用 CSS 实现这个效果。每个图文区块放一张全屏粘性图片,文字叠在图片上方。图片会固定在视口顶部,直到所属区块滚出视口;接着,下一个区块的图片进入视口。整个布局不需要 IntersectionObserver。
原示例中的 height: 100% 需要祖先元素有明确高度,才能得到预期尺寸;同时,图片和文字仍按普通文档流排列。可以让图片占据 100svh 高度,再用负上边距把文字移到图片上方。
示例
<main>
<section class="scene">
<img
class="scene__image"
src="https://placehold.co/600x400/aliceblue/lightgray?text=image-1"
alt="第一张背景图"
>
<div class="scene__content">
<p>第一段文字内容。文字较长时,会继续向上滚动,图片则在本区块内保持粘性。</p>
</div>
</section>
<section class="scene">
<img
class="scene__image"
src="https://placehold.co/600x400/lightyellow/lightgray?text=image-2"
alt="第二张背景图"
>
<div class="scene__content">
<p>第二段文字内容。滚动到这个区块后,第二张图片会成为粘性背景。</p>
</div>
</section>
</main>
.scene {
position: relative;
}
.scene__image {
position: sticky;
top: 0;
z-index: 0;
display: block;
width: 100%;
height: 100svh;
object-fit: cover;
}
.scene__content {
position: relative;
z-index: 1;
margin-top: -100svh;
padding: 2rem;
color: white;
}
为什么图片能保持固定
滚动时,position: sticky 会让图片停留在 top: 0。这种效果受所属滚动容器和父区块的范围限制。每张图片都在自己的 .scene 中,因此会一直保持粘性,直到该区块滚出视口。之后,下一个 .scene 进入视口,显示其中的图片。
.scene__content 的负上边距会把文字移到图片区域,z-index 则控制文字显示在图片上方。需要给文字添加背景时,可以设置半透明背景色,例如 background: rgb(0 0 0 / 40%);。
调整时需要注意
height: 100svh会让图片铺满动态视口高度。若要兼容不支持svh的浏览器,可以先写height: 100vh,再用100svh覆盖。object-fit: cover会保持图片比例并裁切多余部分。若不希望裁切,可以改用object-fit: contain,但可能会出现空白区域。- 图片应放在包含其滚动内容的区块内。如果祖先元素设置了
overflow: auto、hidden或scroll,粘性定位可能会以该祖先为参照,表现也会有所不同。 - 文字短于视口时,图片本身的
100svh高度会让区块至少占据一屏。文字较长时,区块会随内容增高,图片则在区块内保持粘性,直到区块结束。 - 需要实现更复杂的触发动画或状态变化时,可以考虑
IntersectionObserver。单纯实现粘性滚动和图片切换,用 CSS 即可。
备注:内容仅供参考。
