经常在网上冲浪,看到那种特别炫酷的滚动动画,比如文字随着手指滑动像漩涡一样转起来,心里就痒痒的。但有时候拿手机一刷,好家伙,直接卡成PPT,甚至直接黑屏罢工。那些用JS硬刚出来的效果,在性能面前多少有点力不从心。其实,现在CSS里藏着不少新宝贝,能把这种高难度的滚动动画从主线程的“重体力活”变成GPU加速的“丝滑小连招”。
核心战力:sibling-index()
这玩意儿是干啥的
在CSS里,sibling-index() 就像给一群排队的小朋友发了个号码牌。它能精准知道当前元素在它所有兄弟元素里排第几位。这个功能加上它的好搭档 sibling-count(),相当于让CSS拥有了简单的“数数”能力,不用JS在背后计算,就能根据元素的位置来动态调整样式。
怎么给文字排兵布阵
要实现那个文字漩涡,第一步就得把一句话拆成一个一个独立的“兵”。这波操作虽然得请JS来帮忙拆开文本,但拆完之后的动画全交给CSS跑,性能稳得很。
<div class="vortex">
<div class="char">这</div>
<div class="char">是</div>
<div class="char">一</div>
<div class="char">个</div>
<div class="char">字</div>
<!-- 后面的字依次排列 -->
</div>坑位预警:拆分的时候,空格最容易翻车。如果不对空格做特殊处理,它可能会消失不见,导致文字全粘在一起。通常的骚操作是把普通空格替换成一个“占位空格”,让插件也把它当成一个独立的字符盒子来处理。
从静态文字到动态漩涡
搭建螺旋舞台
所有字符的父容器 .vortex 是这场表演的大舞台。给它加上 position: fixed 和 left: 50% 是为了让整个漩涡始终固定在屏幕中间。重点是用 animation-timeline: scroll() 把动画和滚动进度绑定起来,滑多少,转多少。
性能玄学:父容器的动画只是整体的缩放和旋转,这种变换在GPU里跑得飞快,不会给主线程添堵。
给每个字符算算“座位”
每个字符的 --radius 和 --rotation 变量是关键。借助 sibling-index(),第一个字符离中心最远,最后一个字符几乎贴到中心,同时每个字符的角度也都不一样,均匀分布在圆周上。这样一来,所有字符自然就摆成了一个螺旋形。
.vortex {
position: fixed;
left: 50%;
height: 100vh;
animation-timeline: scroll();
.char {
--radius: calc(10vh - (7vh/sibling-count() * sibling-index()));
--rotation: calc((360deg * 3/sibling-count()) * sibling-index());
position: absolute !important;
top: 50%;
left: 50%;
transform: rotate(var(--rotation)) translateY(calc(-2.9 * var(--radius))) scale(calc(.4 - (.25/sibling-count() * sibling-index())));
animation-timeline: scroll();
}
}翻车现场:公式里的系数,比如 10vh、7vh 这些数值,得根据文字数量和屏幕大小反复调。如果直接照搬别人的数值,在小屏手机上看可能就成一坨浆糊。
让漩涡转起来,字一个一个亮
为了让效果更带感,除了位置螺旋,还可以让文字在滚动中逐渐显现。利用 animation-range-start 配合 sibling-index(),让每个字符的淡入时机错开。先出现的字符先亮,后出现的后亮,滚动时就有种一层层被吸进去的视觉冲击。
.char {
animation-name: fade-in;
animation-range-start: calc(90%/sibling-count() * sibling-index());
animation-fill-mode: forwards;
animation-timeline: scroll();
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}节奏把控:90% 这个基准值决定了动画的起始点。如果设得太高,可能都滑到底了字还没亮完;设得太低,字又亮得太早,失去了悬念感。
方案二:纯CSS的极简螺旋(不依赖拆分)
如果觉得把每个字拆开太麻烦,或者想快速实现一个类似的螺旋效果,可以直接用一个 <div> 包住所有文字,然后给这个容器做旋转和缩放。
<div class="simple-vortex">
<p>这里是一段完整的文字,不需要拆开</p>
</div>.simple-vortex {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation-timeline: scroll();
animation-name: vortex-suck;
animation-duration: auto;
animation-fill-mode: forwards;
}
@keyframes vortex-suck {
from {
transform: translate(-50%, -50%) scale(1) rotate(0deg);
opacity: 1;
}
to {
transform: translate(-50%, -50%) scale(0) rotate(720deg);
opacity: 0;
}
}适用场景:这种玩法适合做整体的转场效果,比如一段提示语或者品牌名,滚动时直接旋转缩小消失。虽然不如拆字那么酷炫,但胜在代码量少,兼容性也更好,手机上跑起来一点压力都没有。
