CSS view():以后做滚动动画不用写JS了

摘要:以前做滚动动画,一看代码里有scroll监听、getBoundingClientRect()、节流、防抖,还要自己算进度条,我就知道后面要麻烦了。不是说不能写。是这种代码一多,动画、性能、后面好不好改

以前做滚动动画,一看代码里有scroll监听、getBoundingClientRect()、节流、防抖,还要自己算进度条,我就知道后面要麻烦了。

不是说不能写。是这种代码一多,动画、性能、后面好不好改,这三样经常都保不住。浏览器明明自己就知道元素有没有进到视野里、滚动到哪了,结果我们非要用JavaScript再算一遍。

现在这事,CSS已经接过去一大块了。滚动动画可以直接跟滚动条走,view()就是里面最好用的一个。它会根据元素在滚动容器里的可见程度来推动动画。


以前要写一大堆代码

很多人以前是这么写的:

const cards = document.querySelectorAll('.card')

function update() {
  const vh = window.innerHeight
  
  cards.forEach((card) => {
    const rect = card.getBoundingClientRect()
    const start = vh * 0.9
    const end = vh * 0.2
    const progress = Math.min(
      1,
      Math.max(0, (start - rect.top) / (start - end))
    )
    
    card.style.opacity = progress
    card.style.transform = `translateY(${(1 - progress) * 40}px)`
  })
}

window.addEventListener('scroll', update, { passive: true })
window.addEventListener('resize', update)
update()

这段代码不是随便写的例子,很多线上项目真就这么干的。问题也很明显:

第一,你得自己算“什么时候开始进场、什么时候算结束”。

第二,页面一复杂,滚动的不止是整个页面,还有里面的小区域,判断就开始乱。

第三,动画逻辑全散在JS里,样式和行为搅在一起,后面谁接手谁头疼。


用view()怎么写

换成view(),思路就清爽多了:

.card {
  opacity: 0;
  transform: translateY(40px);
  animation: card-in both linear;
  animation-timeline: view();
  animation-range: entry 20% cover 40%;
}

@keyframes card-in {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
html
订单服务
库存服务
通知服务

这里没写一行滚动计算的代码。元素滚进视野,动画自己动;往回滚,动画也跟着倒回去。这个机制说白了就是“动画走到哪跟滚动条走到哪绑在一起”,不像以前那样时间到了自己播完。


view()适合干什么

我自己会拿它做这几类东西:

  • 页面往下翻的时候,卡片一个个淡入

  • 文章里的章节标题、配图、时间线进场

  • 那种“滚到哪一块,哪一块亮起来”的简单效果

这类动画以前最烦人的不是写不出来,是你得一直维护那套“滚动位置转成动画进度”的代码。现在浏览器自己能管,就别自己扛着了。


再来个例子

做一个侧边目录高亮的效果,同样不用碰JS:

.doc-block {
  --p: 0;
  animation: block-focus both linear;
  animation-timeline: view(block);
  animation-range: entry 10% cover 30%;
}

@keyframes block-focus {
  from {
    opacity: .5;
    transform: scale(.98);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

这里的view(block)意思是沿着块方向跟踪可见进度。view()可以加轴参数,也能调inset来改“多早算进入视野”。


这东西也有毛病

第一,现在还不是所有浏览器都支持。MDN上标的“Limited availability”,就是说主流浏览器还没全覆盖。真要用在正式项目上,还是得看看你的用户用什么浏览器。

第二,它代替不了所有JavaScript。你要做复杂的联动、跟数据挂钩的动画、滚动和业务状态绑得紧的,JS还是得上。但那种只是“元素滚进来动一下”的需求,再写满屏监听和计算,就有点说不过去了。


说句实在话

更准确的说法不是“JavaScript滚动动画死了”,是很多本来就不该让JS管的滚动动画,终于可以还给CSS了。

前端这几年有些进步我是真喜欢,不是功能变花哨了,是浏览器终于开始接手那些本来就该它干的累活。view()就属于这种。能少写一段滚动监听,就少留一个掉帧的地方。文章页、官网、活动页,用这个东西能省你不少事。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_13740