网页上那些随着滚动条滚啊滚,图片突然变大变清晰的效果,是不是看着特别酷?以前要实现这玩意儿,可能得请出JavaScript大佬,还得搬出Intersection Observer才能搞定。现在不一样了,CSS亲自动手,直接给安排了个叫animation-timeline的狠角色。这货带上view()函数,就能让动画不再依赖时间,而是看元素在滚动窗口里露了多少脸。简单说,就是元素滚到哪儿,动画就跑到哪儿,妥妥的跟屁虫。
先整个架子
要做个能滚动的小玩意儿,最基本的得有个装东西的盒子。就拿常见的那种横向滚动图集来说,整个大盒子当容器,里面塞上一排排的图片卡片就行。
<main class="rolling-box">
<div class="roll-item">
<!-- 开头可以放个空的占位 -->
</div>
<div class="roll-item">
<img src="pic-1.jpg" alt="风景照1">
</div>
<div class="roll-item">
<img src="pic-2.jpg" alt="风景照2">
</div>
<!-- 中间多来几张 -->
<div class="roll-item">
<!-- 结尾也放个空的,让滚动更丝滑 -->
</div>
</main>盒子搭好了,得给它点样式。让它里面的东西排成一排,还得能左右划拉。
.rolling-box {
display: flex;
width: max(480px, 50vw);
overflow-x: auto;
}
.rolling-box .roll-item {
flex-shrink: 0;
width: calc(100% / 3); /* 一次露三张,刚刚好 */
aspect-ratio: .8;
img {
width: 100%;
}
}这样一弄,一个可以左右滑动的小玩意儿就成型了。为了让滑动更有手感,可以加点吸铁石一样的滑动吸附效果。
.rolling-box {
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
scrollbar-width: none;
}
.roll-item {
scroll-snap-align: center;
}这步做完,滑动的时候每一张图都会稳稳地停在中间,手感立马就上来了。在这里需要注意的是,scrollbar-width: none只是把滚动条藏起来,不是让它消失,如果用户用的鼠标滚轮,还是能正常滚动的。
动画整起来
动画这玩意儿,以前怎么写,现在还怎么写。就是弄个关键帧,定义好从哪儿开始,到哪儿结束。咱们想要的效果是,在边上的图模糊又小,滚到中间就变得又大又清晰。
@keyframes focusIn {
45%, 100% {
transform: scale(0.6);
border-radius: 20px;
filter: blur(5px) brightness(.7);
}
50% {
transform: scale(1);
border-radius: 5px;
filter: none;
}
}这个关键帧看着眼熟吧?跟平常写动画一模一样。接下来就是把动画绑到每个图片卡片上,但是跟以前不一样,这次不按时间线走。
.roll-item {
animation: focusIn;
animation-timeline: view(inline);
}就这一句animation-timeline: view(inline),直接把动画的节奏从“时间到了”换成了“滚动到了”。现在试试,每划动一下,图片的变化都跟着它在滚动窗口里的位置走,这效果简直yyds。有一点千万得记住,写animation-timeline的时候,最好放在animation简写属性的后面,不然可能会被默认的auto给覆盖掉,到时候动画就不跟着滚动了。
进阶玩法
光会用view()还不够,括号里其实还能塞点东西,让它更听话。view()可以接受两个参数,一个是方向(block、inline、x、y),一个是偏移量(inset)。这个偏移量可太实用了,它决定了动画什么时候开始触发。
比如说,想让图片刚露出一丢丢就开始变,完全离开窗口才结束,就可以调整这个偏移量。下面这段代码就能让动画在元素进入窗口时就启动,而不是等它完全跑出去。
.roll-item {
animation: focusIn linear both;
animation-timeline: view(100% 0%);
}这样一来,动画的触发时机就精准多了,不会出现那种一张图都滚到中间了才开始变化的尴尬场面。另外,还有个叫animation-range的属性也能干类似的事儿,比如animation-range: entry,意思就是元素进入滚动窗口的范围时触发动画,这两个属性配合着用,能把动画触发点拿捏得死死的。
再加点料
为了让轮播图不那么单调,还能玩点花的。比如给背景位置加点动画,让背景自己溜达,看起来像在平移一样。
| 动画属性 | 效果描述 |
|---|---|
| 背景位置 | 缓慢移动 |
| 缩放比例 | 近大远小 |
| 模糊程度 | 由虚变实 |
把这些效果组合一下,就能做出那种背景跟随鼠标或者滚动慢慢移动的感觉,视觉冲击力直接拉满。
@keyframes moveBg {
0% {
background-position: 0% 50%;
filter: blur(4px);
}
100% {
background-position: 100% 50%;
filter: blur(0px);
}
}
.roll-item {
background-image: url('cool-bg.jpg');
background-size: cover;
animation: moveBg linear both;
animation-timeline: view();
}看到没,只要想象力够丰富,view()能玩出的花样多到数不清。从简单的图片缩放,到复杂背景移动,甚至还能结合@property去搞渐变角度的变化,把以前那些得靠JS才能做的交互,现在全交给CSS搞定。
