资讯动态

CSS动效四件套:音视频嵌入、过渡、变形、动画实战指南

发布时间:2026/10/18 4:11:08 来源:尧图企业网站定制
直接说结论CSS远不止改颜色、调布局这么简单。真正让页面活起来的是音视频嵌入、过渡、变形、动画这四件套。这篇东西不整虚的我把四个部分的原理、实操代码、坑点和排查思路全部摊开讲适合刚学完Flex和Grid、想进一步让页面动起来的人也适合写了好几年样式但遇到动画卡顿、音频不播、3D旋转失灵时回来翻一翻的老手。1. 内容整体设计与思路拆解1.1 为什么把这四个方向放在一起讲很多人学CSS是零散地学今天看了个视频说transition很好用明天又搜到transform: rotate()做翻转后天做首页的时候发现video标签插进去却黑屏。知识是碎片化的用的时候根本串不起来。把这四样放在一起有一个底层逻辑它们共同构成了CSS表现层的动态体系。音视频把非文本内容塞进页面解决内容来源的问题。过渡transition解决状态A变到状态B怎么变的问题。变形transform解决元素本身怎么做位置、角度、尺寸上的几何变化的问题。动画animation解决预设多帧变化让元素自主运行的问题。在实际项目里四者经常是协同作战的。比如一个产品展示页背景放视频音视频插入鼠标悬停时卡片上浮并翻转过渡变形进入视口时从底部升上来动画……你单独会某一个能力只能做能动的页面理解四者的分工和配合才能做有节奏的页面。1.2 先建立一个正确的性能心智模型在讲任何代码之前必须先讲性能。因为在CSS动态效果里最大的坑不是写不出来而是写出来之后掉帧、卡顿、CPU占用飙高。浏览器的渲染流水线大致是解析HTML/CSS - 计算样式 - 布局Layout- 绘制Paint- 合成Composite。不是所有属性触发这条完整链路。改width、left、top、margin触发Layout开销最大。改background-color、box-shadow触发Paint开销中等。改transform、opacity只走Composite由GPU加速开销最小。所以业界有一条不成文的规矩能用transform和opacity做的动画就别用width和top去做。这也是为什么下面讲变形和动画的时候大量操作都是围绕transform展开的。这个认知如果你第一次接触建议直接刻在脑子里它决定你后面写的动画是丝滑还是卡成PPT。1.3 四种能力的适用边界先给出一个整体的选用思路免得你动手时拿不准需求类型首选方案原因页面上要放一段视频/音频video/audio标签原生支持无需插件悬停、点击时状态平滑变化transition轻量、由状态驱动元素旋转、缩放、位移、倾斜transform高性能几何变换自动播放、多帧编排的循环动画keyframesanimation时间轴控制表现力最强状态变化 几何变化同步transitiontransform最常用的组合拳需要特别提醒的是过渡、变形、动画三者不要混为一谈。过渡是补间它关注的是两个状态之间的差值如何被填充变形是结果它描述元素最终被几何加工成什么样动画是过程它定义随时间推进的一连串关键帧。三者互为补充但不能互相替代。2. 核心细节解析与实操要点2.1 音视频插入不只是加标签那么简单HTML5原生支持音视频这是最可靠的方案。基础语法极其简单video srcintro.mp4 controls/video audio srcbgm.mp3 controls/audio但项目落地时你很快会遇到三个绕不开的问题。第一个问题是格式兼容。不同浏览器支持的编码格式并不完全一致。保险做法是提供多种格式源浏览器自己挑第一个能播的video controls source srcintro.webm typevideo/webm source srcintro.mp4 typevideo/mp4 你的浏览器不支持视频播放。 /video这里给小白解释一下controls属性它让浏览器显示自带的播放控件包括进度条、音量、全屏按钮。如果去掉它视频画面会被渲染出来但你没有任何操作按钮——这在某些需要完全自定义播放器的场景是有意为之但新手阶段请老老实实加上。第二个问题是自动播放策略。移动端和桌面端的浏览器普遍限制带声音的自动播放这是产品经理最常提、前端最头疼的需求之一。常规变通方式是静音自动播放video autoplay muted loop很多网站的首页背景视频都这么干。用户交互后播放在页面的点击事件里调用video.play()此时浏览器允许带声音播放。音频自动播放基本不要指望只有极少数用户手势后才能启动。第三个问题是样式控制。video标签虽然看起来像个普通元素但它的内置控件在不同浏览器里长得完全不一样。如果你想统一风格两种思路一是用::-webkit-media-controls系列伪元素去覆盖WebKit内核的控件样式但兼容性有限二是隐藏原生控件去掉controls自己用DOM加上播放/暂停按钮、进度条通过JavaScript控制播放。项目里只要是定制化程度高的基本都走第二条路。音频同理audio标签在页面上默认是不可见的。你做音乐播放器的时候一定是自己画按钮、绑事件原生标签只负责解码和出声。2.2 过渡transition状态之间要渐变而不是突变transition的四个子属性分别是transition-property、transition-duration、transition-timing-function、transition-delay。合起来写.button { background-color: #333; transition: background-color 0.3s ease-in-out; } .button:hover { background-color: #ff6b6b; }当鼠标悬停时背景色不会瞬间从深灰跳到红色而是在0.3秒内平滑变化。这个过程中浏览器自动计算中间帧。写transition的时候三个易错点你必须心里有数。第一个不是所有属性都能过渡。常见可过渡属性包括颜色、透明度、尺寸、间距、阴影等而display这种离散属性不可过渡典型场景是悬停时把隐藏的子菜单显示出来很多人写成display: none - block再加transition结果发现完全没有动画效果。正确做法是结合opacity和visibility或者用max-height做高度展开.dropdown { max-height: 0; opacity: 0; overflow: hidden; transition: max-height 0.4s ease, opacity 0.3s ease; } .dropdown.open { max-height: 300px; opacity: 1; }第二个transition需要触发条件。它本身不会主动执行必须依赖某个状态变化比如:hover、:focus、新增class等。如果你希望页面加载时就自动播放变化那应该用animation而不是transition。第三个隐藏了属性名会出问题。如果你写transition: all 0.3s方便是方便但对所有属性生效可能会导致意外过渡比如width变化时的布局抖动。性能敏感场景更不应该用all。2.3 变形transform几何变换的“底层引擎”transform支持四类基础变换位移translate、旋转rotate、缩放scale、倾斜skew。又可以拆成2D和3D两套。2D变换的常用写法.card:hover { transform: translateY(-8px) scale(1.02) rotate(1deg); }这行的意思是悬停时元素向上平移8像素、放大到1.02倍、轻微旋转1度。注意多个变换函数写在同一行时顺序会影响最终效果。比如先旋转再平移和先平移再旋转结果不一样。因为变换是按从右到左的顺序应用到元素坐标系上的。3D变换要稍微多说几句因为它涉及perspective透视的概念。没有透视3D旋转看起来只是一个扁平的缩放。透视可以加在父容器上也可以加在元素自身.scene { perspective: 800px; } .cube { transform: rotateY(45deg) rotateX(30deg); }perspective值越小透视效果越强烈元素近大远小的感受越明显。通常800到1200px看起来比较自然。还有一个高频坑transform会创建新的层叠上下文和包含块。简单说给元素加了transform之后它对于内部position: fixed;子元素的行为可能会发生变化浮动和定位的坐标系也会受影响。某些老项目中你给一个元素设置transform后里面的position: fixed弹窗突然不跟着视口走了多半就是这个原因。2.4 动画animation用关键帧编排“时间轴”animation系属性比transition复杂得多核心是keyframes。基本结构keyframes floatIn { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .hero-title { animation: floatIn 0.8s ease-out forwards; }from和to是简写相当于0%和100%。你可以写任意多个百分比节点编排更复杂的动作keyframes swing { 0% { transform: rotate(0deg); } 40% { transform: rotate(20deg); } 70% { transform: rotate(-10deg); } 100% { transform: rotate(0deg); } }swing这个动画模拟了一个先向右摆、回弹向左、最后归位的过程。这就是关键帧动画的核心思路你不需要描述每一帧只需要规定几个关键时刻的状态浏览器自动补间。配置动画时animation是一个复合属性注意区分两个容易混淆的值infinite无限循环播放。forwards动画结束后保留最后一帧的状态。如果没写这个动画结束的瞬间元素会跳回初始样式。alternate奇数次正向播放偶数次反向播放适合做往复摆动效果。实操中最常见的困惑是为什么动画结束后元素又跳回去了就是因为忘了加forwards。另一个常见困惑是加了transform的动画为什么位移起点不对多半是因为keyframes里的关键帧状态和元素自身的静态样式没有统一浏览器以关键帧为准但结束后的跳变又以静态样式为准。3. 实操过程与核心环节实现下面用一个完整的示例串起全部四个内容做一个产品介绍页中的一个卡片区块背景加视频卡片悬停有过渡和变形卡片入场有动画。这算是比较典型的个人项目练手Demo我按完整步骤写你跟着敲一遍就能跑。3.1 搭音视频底衬先声明一下我这里示例里的媒体资源文件你需要自行准备或者换成网络上的公开测试资源。核心是看结构。section classshowcase video classbg-video autoplay muted loop source srcbg.webm typevideo/webm source srcbg.mp4 typevideo/mp4 /video div classcontent !-- 卡片们放这里 -- /div /section样式部分视频要盖住整个区块但不能挡住文字交互.showcase { position: relative; overflow: hidden; } .bg-video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; } .content { position: relative; z-index: 1; }这里object-fit: cover是视频和图片的通用技巧作用是让媒体内容等比缩放并填满容器超出部分裁掉避免变形。z-index确保内容层在视频层上方。overflow: hidden是防止视频撑破圆角或容器边界。如果你用的是音频做背景音乐则不需要渲染层直接把audio标签放到任意位置用JavaScript控制播放即可。但切记自动播放限制——除非用户点过页面否则大概率被拦。3.2 写卡片结构和基本样式卡片本身是普通的DOM结构div classcard-grid article classcard h3基础功能款/h3 p适合日常展示场景支持悬停动效。/p a href#查看详情/a /article article classcard h33D展示款/h3 p带透视翻转效果适合产品陈列。/p a href#查看详情/a /article article classcard h3全动态款/h3 p入场加载动画无限循环动效。/p a href#查看详情/a /article /div基础样式先摆正.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; max-width: 1080px; margin: 0 auto; padding: 60px 20px; } .card { background: rgba(255, 255, 255, 0.92); border-radius: 16px; padding: 32px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); transition: transform 0.35s ease, box-shadow 0.35s ease; }这步其实已经用了transition不过是静态过渡。好处是当悬停状态发生改变时卡片能平滑地做出反应而不是瞬跳。3.3 加入悬停过渡与变形核心部分来了。给三种卡片分别设计悬停表现.card:hover { transform: translateY(-10px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); } .card:nth-child(2) { transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); } .card:nth-child(2):hover { transform: rotateY(8deg) rotateX(4deg) scale(1.02); } .card:nth-child(3) { transition: transform 0.45s ease; } .card:nth-child(3):hover { transform: scale(1.05) rotate(-1deg); }第二张卡件的cubic-bezier(0.34, 1.56, 0.64, 1)是回弹曲线数值超过1会让过渡产生一点超出目标位置的弹性视觉上更活泼。而第一张卡用的是默认的ease更稳重。这里你能直观看到过渡曲线选择对交互质感的影响。需要补充的是transform写在两个地方时会出现覆盖逻辑.card的静态样式里没有写transform:hover里写了所以只有悬停时变形才会激活。如果静态样式和:hover里都写了transform悬停时的写法会完全覆盖静态的写法而不是叠加。例如静态是scale(1)悬停是translateY(-10px)那么悬停时不会同时缩放和平移后者会覆盖前者。想要叠加必须把两个函数写在同一行transform: translateY(-10px) scale(1)这一点务必记住。3.4 加入入场动画上面说的都是悬停动效下面用keyframes和animation实现卡片列表加载时的入场效果。先用一个立方体旋转的动画来示例3D变换和动画的组合keyframes cardEntrance { 0% { opacity: 0; transform: translateY(40px) scale(0.95); } 100% { opacity: 1; transform: translateY(0) scale(1); } } .card { animation: cardEntrance 0.6s ease-out both; } .card:nth-child(1) { animation-delay: 0s; } .card:nth-child(2) { animation-delay: 0.15s; } .card:nth-child(3) { animation-delay: 0.3s; }both是animation-fill-mode的一个值等价于backwardsforwards动画开始前先把0%关键帧的状态应用上动画结束后保持100%关键帧的状态。在这里both保证了页面加载瞬间所有卡片先处于透明下移的初始状态再依次入场。没有both或backwards的话延迟时间内卡片会以完整状态显示然后突然消失再重新入场闪一下观感很糟。三个延迟时间形成依次进场的视觉节拍这是做列表入场动画最基础的做法。实际项目里可以用JavaScript根据索引动态设置animation-delay但CSS也完全够用。3.5 做一个组合示例3D旋转卡片把音视频背景、悬停过渡、变形、进场动画全部整合一起时需要注意进场动画用transform悬停变形也用transform两者在动画结束后会产生冲突吗答案取决于动画是否结束。只要animation运行期间关键帧里的transform优先级高于普通样式。动画结束后如果设置了forwards或both关键帧的最后一帧会一直覆盖普通样式此时悬停的transform会失效。解决办法是不要给同一个元素的入场动画和悬停变形都设置transform要么让动画最后一帧的transform为none然后把变形包在子元素上要么动画结束后移除动画类。这里推荐的结构是外层元素做入场动画opacity和translateY内层元素做悬停变形rotateY和scale。互不干扰article classcard card--entrance div classcard-inner h3产品型号A/h3 p完整的产品描述。/p /div /article.card--entrance { animation: cardEntrance 0.6s ease-out both; } .card-inner { transition: transform 0.4s ease; } .card--entrance:hover .card-inner { transform: rotateY(10deg) scale(1.02); }这是我在实际项目里最常用的分层思路动画层、交互层、内容层分离各管各的样式属性少踩很多没必要的坑。4. 常见问题与排查技巧实录4.1 视频不显示、黑屏或无法自动播放排查按三步走。第一确认资源路径和编码格式。右键视频文件看属性比如.mp4文件编码是H.264还是HEVC浏览器支持度不同。换成webm格式通常兼容性更好。用浏览器直接打开视频URL看是否能在浏览器里直接播放这是一个很有效的定位手段。第二确认自动播放策略。如果你写了autoplay但没写muted几乎必然被拦截尤其移动端。视频想自动播放请同时设置autoplay、muted、loop。第三检查元素尺寸。video没有width和height时默认尺寸可能是300x150。如果容器很小且没有显式给视频设宽高看起来就像没显示。加一条width: 100%; height: 100%; object-fit: cover基本能解决。4.2 transition没生效或者瞬间完成最常见的原因是你只写了transition-property或者只写了transition-duration而复合属性不完整。transition要在状态变化前就定义在元素上不是定义在:hover状态上。如果你把transition写在:hover里鼠标移入时浏览器才去应用过渡配置但状态已经突变完了所以你只能看到移出时的过渡移入时是瞬变。另一个原因是你过渡的属性在计算上不可过渡。比如display: none到display: block这种属性没有中间态。按照前面说的换用opacityvisibility组合或者max-height方案。还有一个隐蔽的原因元素本身设置了animation-fill-mode: forwards且动画仍在运行动画的关键帧会对相同属性拥有更高优先级导致transition失去作用。此时暂停动画或分开元素即可。4.3 3D旋转看起来像2D缩放没有立体感这个问题的原因高度统一缺少perspective。perspective必须加在需要3D透视的元素的父容器上或者作为transform的第一个函数写进元素自身例如transform: perspective(800px) rotateY(45deg)。只给子元素加rotateY父容器没有perspective视觉上只是宽度在缩放毫无立体感。给父容器加上perspective: 900px;之后立刻会出现近大远小效果。另外如果还需要子元素保持真正的3D空间比如卡片翻面后看到背面内容父容器还需要transform-style: preserve-3d;。4.4 animation动画结束又跳回原位原因在之前提过animation-fill-mode没有设置forwards或both。动画结束后浏览器会把元素的样式回滚到没有动画时的静态样式。如果你的动画终点状态100%关键帧和静态样式不一致就会看到明显的跳变。如果想保留终态就加forwards如果想动画开始前也保持初态就加backwards一般我直接用both简单粗暴。如果不想保留终态而是动画结束后自然回到原样那就不用管它。4.5 动画卡顿、掉帧怎么排查和优化优先检查你是不是在动画里动了width、height、top、left、margin这些触发布局的属性。如果是换成transform来实现位移和缩放。例如元素从左移到右用transform: translateX()代替left。元素变大变小用scale()代替width/height。其次检查是不是图层太多、合成负担重。可以使用浏览器开发者工具的Performance面板录制一段动画看帧率FPS是否稳定在60附近。如果掉到30甚至更低把不需要同时动画的元素数量降下来或者用will-change: transform提示浏览器提前优化但不要滥用否则内存占用会上升。再一个容易被忽略的点动画中box-shadow和filter如blur非常耗性能。它们一旦动起来每帧都要重新计算阴影和模糊掉帧概率极高。如果必须用阴影动效优先考虑用透明度渐变的伪元素模拟或者缩短动画时长、缩小作用元素面积。4.6 常见问题速查表症状原因解决视频黑屏/无法自动播放格式不兼容或自动播放策略拦截提供webm/mp4双源加muted悬停瞬间变色/位移没有过渡transition写在:hover里或属性不可过渡把transition写在元素常态样式中3D旋转看起来像缩放父容器缺少perspective给父容器加perspective动画循环时动作不顺滑keyframes末帧与首帧状态不连续保证0%和100%状态一致或用alternate动画结束元素跳回原点缺少animation-fill-mode加forwards或both动画卡顿使用了布局属性或高开销属性改用transform/opacity两个transform互相覆盖静态样式与关键帧样式冲突分层写或统一写在同一次声明里4.7 分享几个走出来比较有价值的排查心得拿我个人经验来说调试CSS动效最有效的工具还是浏览器开发者工具里的样式面板加动画控制。Chrome的开发者工具在Styles面板里能显示正在应用的动画并且支持拖动时间线来逐帧预览。碰到动画问题先把元素状态一步步拆开看静态样式、关键帧样式、伪类样式逐一禁用定位到底哪一条规则在起作用。还有一个习惯动画逻辑尽量集中在CSS里不要用JavaScript的setInterval去改样式实现动画。一旦大量使用JS驱动的样式修改布局计算会频繁发生性能比CSS动画差一个量级。CSS能做到的就不要让JS重复造轮子。5. 完整示例把四者组合成一个可用模块前面的内容比较分散这里给一个可以直接复制运行的完整HTML文件包含视频背景、表格卡片、入场动画、悬停过渡变形。文件里如果有不能访问的视频源替换成本地文件即可。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleCSS动态效果组合示例/title style * { margin: 0; padding: 0; box-sizing: border-box; } :root { --card-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); --card-shadow-hover: 0 18px 40px rgba(0, 0, 0, 0.16); } body { font-family: PingFang SC, Microsoft YaHei, sans-serif; background: #f5f6f8; color: #222; } .showcase { position: relative; overflow: hidden; min-height: 420px; display: flex; align-items: center; justify-content: center; } .bg-video { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; } .showcase .overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.35); z-index: 1; } .content { position: relative; z-index: 2; text-align: center; color: #fff; padding: 40px 20px; } .content h1 { font-size: 40px; margin-bottom: 12px; text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); } .content p { font-size: 18px; opacity: 0.9; } .card-grid { position: relative; z-index: 2; display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; max-width: 1080px; margin: -40px auto 40px; padding: 0 20px; } .card { background: rgba(255, 255, 255, 0.95); border-radius: 16px; padding: 32px; box-shadow: var(--card-shadow); animation: cardEntrance 0.6s ease-out both; } .card:nth-child(1) { animation-delay: 0s; } .card:nth-child(2) { animation-delay: 0.15s; } .card:nth-child(3) { animation-delay: 0.3s; } .card h3 { font-size: 20px; margin-bottom: 12px; } .card p { font-size: 15px; line-height: 1.6; color: #555; margin-bottom: 20px; } .card a { display: inline-block; padding: 8px 20px; border-radius: 999px; background: #2c3e50; color: #fff; text-decoration: none; font-size: 14px; transition: background-color 0.25s ease, transform 0.25s ease; } .card a:hover { background: #ff6b6b; transform: scale(1.04); } .card--flip { transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.4s ease; } .card--flip:hover { transform: rotateY(6deg) rotateX(3deg) translateY(-8px); box-shadow: var(--card-shadow-hover); background: #fff; } keyframes cardEntrance { 0% { opacity: 0; transform: translateY(40px) scale(0.95); } 100% { opacity: 1; transform: translateY(0) scale(1); } } media (max-width: 768px) { .card-grid { grid-template-columns: 1fr; } } /style /head body section classshowcase video classbg-video autoplay muted loop source srcbg.webm typevideo/webm source srcbg.mp4 typevideo/mp4 /video div classoverlay/div div classcontent h1动态效果实战展示/h1 p视频背景 入场动画 悬停变形与过渡/p /div /section main classcard-grid article classcard h3基础卡/h3 p支持入场动画按钮悬停有过渡变色。/p a href#查看详情/a /article article classcard card--flip h33D交互卡/h3 p悬停时产生立体翻转效果适合产品陈列。/p a href#查看详情/a /article article classcard h3组合应用卡/h3 p入场动画与内部元素动效分离互不冲突。/p a href#查看详情/a /article /main /body /html这个示例使用了.card--flip类来专门承载悬停3D变形。组合应用卡则演示了动画层在外、过渡层在内的思路外层卡片的入场动画结束后内部的a标签的悬停变形和颜色过渡依然可以正常工作互不干扰。如果你把.card--flip类和入场动画直接放在同一个元素上动画结束后因为both模式的存在关键帧的transform: translateY(0) scale(1)会一直覆盖悬停的transform: rotateY(6deg) ...导致悬停立体效果完全失效。这正是我前面强调的冲突场景你可以故意改回去试一下理解会更深。我当年踩过这个坑之后养成了一个习惯凡是同一个元素上既要动画又要交互变形的一律拆成嵌套结构外层管动画内层管交互。这个习惯后来帮我省了无数调试时间也希望你直接用上。6. 风格化的细节过渡曲线、动效节奏与可访问性6.1 动效节奏决定了页面的质感新手和资深前端做出来的动画往往代码能力差不多差的是对节奏的把握。举几个我常用的参数小反馈按钮悬停、图标变化0.15s到0.25s。太短则生硬太长则拖沓。中规模卡片浮起、面板展开0.3s到0.5s。大规模页面切换、弹层进出0.5s到0.8s。过渡曲线也影响节奏感知。linear适合进度条这类持续匀速运动的场景ease-in适合离场像物体被推走ease-out适合进场像物体滑入后减速停住而带回弹的cubic-bezier(0.34, 1.56, 0.64, 1)适合需要活泼俏皮的反馈。曲线的实质是速度变化你可以把它理解为动画的演技。6.2 别忘了尊重用户的系统设置一个我见过很多人忽略的点操作系统提供了减少动态效果的辅助功能设置。一些用户因为眩晕、注意力障碍等原因会主动开启这个选项。作为开发者可以做一个很简单的适配media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.001s !important; transition-duration: 0.001s !important; } }这条规则会把所有动画和过渡的持续时间压缩到几乎为0相当于禁用动效。成本极低但对一部分用户来说体验差异巨大。这个细节很加分尤其是做面向公众的网站时。6.3 让动效有目的而不是为动而动做页面动效前先问自己一句这个动效是为了说明层级关系、引导视觉焦点、还是单纯为了炫如果是单纯炫建议砍掉。好的动效应该给用户传递信息状态变化、元素来源、操作结果。比如卡片入场动画向用户传递这里有新内容出现按钮的缩放过渡传递我被按下了视频背景传递这个页面是多媒体调性。我见过太多页面把所有元素都加上弹跳入场的动画结果用户第一眼根本不知道看哪里。动效是设计语言的一部分克制才是高级。7. 个人经验与几个残留的提醒按我自己的使用频率排个序transform用得最多transition紧跟其后animation在关键节点用音视频插入则根据产品形态看是否需要。如果把这四样比作工具箱transition是螺丝刀transform是电动扳手animation是数控机床音视频是原料。各有各的位置没有谁替代谁。还有几个零碎但重要的点分享给你第一写transition时尽量指定具体属性。虽然all写起来方便但在复杂页面上它会让一些你没预期的属性也跟着过渡。比如你在控制台调试时改了个opacity结果它慢慢变了0.5秒可能反而干扰你的判断。指定属性名之后行为可预期。第二动画不要过多嵌套。一个元素动它的父元素也在动波及下来的合成层可能成倍增加性能问题往往由此而来。做复杂动效时优先保证核心元素的性能辅助元素能动就行不要全员上动画。第三transform和opacity动画确实由GPU加速但GPU内存不是无限的。手机端尤其明显大量图层叠加会导致耗电增加甚至白屏。真机上测一测是你的必修课开发者工具模拟器不能替代真机。第四音视频资源记得做加载策略。页面首屏的视频如果体积过大白屏时间会很长。可以考虑preloadmetadata先加载视频信息或者用poster属性显示一张封面图等用户悬停或点击时再真正加载视频数据。很多人不知道video有poster属性它就是在视频加载完之前显示的静态图片这是非常实用的体验兜底。最后再说一个非常实际的小技巧调试动画卡不卡可以在开发者工具里勾上Rendering - Paint flashing然后播放动画。如果画面上一大片绿色区域在闪烁说明重绘面积很大这时候就要去优化属性。如果是小范围的绿色或没有闪烁基本说明动画走了合成层性能是健康的。这个技巧帮我快速定位过好几个隐蔽的卡顿点比单纯猜性能问题高效太多。CSS的动态能力说难也难说简单也简单。难在性能与兼容的边界简单在核心API就这么多。你只要把每个属性的适用场景和叠加规则吃透再动手做两三个完整Demo基本就能掌握得七七八八。剩下的就是在具体项目里踩坑、填坑、积累手感了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑