原稿:语雀 · CSS 动画 & 常见绘制 · 原目录:CSS › CSS 动画 & 常见绘制
CSS transform
CSS transform允许旋转,缩放,倾斜或平移给定block元素。transform的行为是通过修改CSS视觉格式化模型的坐标空间来实现的——各种变化由transform func相乘叠加,一个func对应一重图层复合操作,因此如果动画中使用transform进行元素坐标和大小调整时无需重排和重绘,对应图层已经被计算出
CSS animation
参考链接:CSS动画-阮一峰
CSS动画主要有三个重要部分:transition(过渡)、animation(动画)、keyframe(关键帧)
transition
曾经CSS中所有的样式都是在即时施加的,CSS3中引入了“transition-过渡”概念,允许指定状态改变所需的时间,借此可以实现延时效果,transition相关有4个属性:
img{ height:15px; width:15px; } img:hover{ height: 450px; width: 450px; } | img{ transition-property: height; transition-duration: 1s; transition-delay: 1s; transition-timing-function: ease; /*transition:height 1s 1s ease*/ } |
|
上面代码实现:hover图片后width立刻50px->450px,1s后高度在1s内由50px->450px | ||
transition局限
transition的优点在于简单易用,但是它有几个很大的局限 2. transition需要事件触发,所以没法在网页加载时自动发生 4. transition是一次性的,不能重复发生,除非一再触发 6. transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态 8. 一条transition规则,只能定义一个属性的变化,不能涉及多个属性
animation
CSS animation为了解决transition的局限
div:hover { animation-name: rainbow; animation-duration: 1s; animation-timing-function: linear; animation-delay: 1s; animation-fill-mode:forwards; animation-direction: normal; animation-iteration-count: 3; /* animation: 1s 1s rainbow linear 3 forwards normal;*/ } | 大部分animation属性类似transition,其中:
|
keyframes
keyframes关键字用来定义动画的各个状态,百分比对应了duration的执行情况,0%可以用from代表,100%可以用to代表 | @keyframes rainbow { from { background: #c00 } 50% { background: orange } to { background: yellowgreen } } | |
通过animation-play-state属性可以设置动画执行时的状态,默认是回到初始状态,右侧代码实现鼠标hover时执行动画,松开时保持当前帧,而不是回到初始 | div { animation: spin 1s linear infinite; animation-play-state: paused; } div:hover { animation-play-state: running; } |
实现1:绘制圆&三角形
圆形比较容易,border-radius:50%,圆角半径设置为盒子的50%即可
三角形,关键是认识到CSS中的每条边框实际是四个三角拼起来的,在其中扣去content即成为border,如果content的宽高都是0,可以得到一个正方形👉 | ![]() | ![]() |
根据这个原理,使用“空content+透明border+非透明border”即可实现三角形
顶点朝上的 等腰三角形 | .triangle-up { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 100px solid red; } | ![]() |
顶点在右上的 等腰直角三角形 | .triangle-top-right { width: 0; height: 0; border-left: 50px solid transparent; border-bottom: 50px solid transparent; border-right: 50px solid red; border-top: 50px solid red; } | ![]() |
实现2:渐变色
渐变实际上是通过background-image的梯度<gradient>实现,许多在线设计器可生成渐变代码
- 线性梯度linear-gradient:单一方向渐变情况
- 径向梯度radial-gradient:沿圆心放射状渐变
.a {
width: 200px;
height: 100px;
margin: 10px 0 10px 0;
background-image: linear-gradient(105deg, rgba(0,249,255,1) 39%, rgba(51,56,57,1) 96%);
}
.b {
width: 200px;
height: 100px;
background-image: radial-gradient(circle, rgba(0,249,255,1) 39%, rgba(51,56,57,1) 96%);
background-size: 100px 50px;
}
<div class="wrapper">
</div>
实现效果如下:
- 左图使用线性梯度,规定渐变轴为105°(默认0°即水平),给定两个渐变色,百分比代表了渐变色终点
- 右图使用径向梯度,给定两个渐变色

实现3:秒针转动效果
使用 animation
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title>clock</title> <style> /* 表盘 */ .second-bar-box { width: 100px; height: 100px; /* 画圆:圆角半径设为盒子宽度50% */ border-radius: 50%; border: 1px solid red; /* 表盘作为定位上下文 */ position: relative; } /* 秒针 */ .second-bar { position: absolute; left: 50%; top: 0; width: 2px; height: 50px; margin-left: -1px; background-color: #ccc; animation: barMove 60s linear infinite; transform-origin: center bottom; } @keyframes barMove { 0% { transform: rotateZ(0deg); } 100% { transform: rotateZ(360deg); }
- 动画代码:animation: barMove 60s linear infinite;
指定barMove作为关键帧,持续时间60s,匀速、循环执行 2. 设置变换基点:transform-origin: center bottom
使用transform-origin设定了元素变换的原点为x轴中点,y轴底部(联系秒针,很好理解) 2. 关键帧代码:0% { transform: rotateZ(8deg); } 100% { transform: rotateZ(360deg); }
使用变换函数rotateZ,以z轴(想成垂直插进屏幕的轴)旋转,需提前设置变换基点,从0°到360°

使用 rAF()
rAF() 可以用来执行无限循环的动画,但是其回调的间隔固定为每秒60次,为了实现精确计时,需要稍微设置: 2. rAF() 60s 内执行3600次 4. 秒针60s内转动360deg,360/3600=0.1deg
则每次回调中使得 retateZ 的角度增长0.1deg,增长到360deg后归零
注意 <script> 需要放在 <body> 后,否则无法获取到文档中的 bar
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>clock</title>
<style>
/* 表盘 */
.second-bar-box {
width: 100px;
height: 100px;
/* 画圆:圆角半径设为盒子宽度50% */
border-radius: 50%;
border: 1px solid red;
/* 表盘作为定位上下文 */
position: relative;
}
/* 秒针 */
.second-bar {
position: absolute;
left: 50%;
top: 0;
width: 2px;
height: 50px;
margin-left: -1px;
background-color: #ccc;
transform-origin: center bottom;
}
</style>
</head>
<body>
<div class="second-bar-box">
</div>
</body>
<script>
let flag = true;
经过测试,60s 时秒针距离12点位置差距极小,因此使用 rAF() 是一个可取的方法
实现4:自动轮播图
参考链接:css实现轮播图
如果要实现一个n张图片(每张宽w,高h)的自动轮播
基本布局 |
|
动画 | 有了以上的布局,先不考虑动画,单纯实现当前图片的改变,可以给slide-items设置margin-left:
加上动画只需在slide-items中设置keyframes,一段时间改变margin-left即可 |
下面实现一个如下的轮播图

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>slide</title>
<style>
.slide-container {
overflow: hidden;
width: 300px;
height: 100px;
margin: auto;
text-align: center;
color: #fff;
}
.slide-items {
/* width要大于等于所有slide-item之和 */
width: 900px;
animation: marginLeft 10.5s infinite;
}
.slide-items .slide-item {
float: left;
width: 300px;
height: 100px;
line-height: 100px;
font-size: 36px;
}
.slide-items .slide-item:nth-child(1) {
background: #9fa8ef;
}
.slide-items .slide-item:nth-child(2) {
background: #ef9fb1;
}
.slide-items .slide-item:nth-child(3) {
background: #9fefc3;
}
@keyframes marginLeft {
/* 0%-25% duration保持margin-left: 0 */
0%,25% {
margin-left: 0;
}
/* 10% duration进行状态改变,变成margin-left: -300px*/
/* 35%-65% duration保持margin-left: -300px */
35%,65% {
margin-left: -300px;
}
/* 下面类似 */
75%,95% {
margin-left: -600px;
}
100% {
margin-left: 0;
}
}
</style>
</head>
<body>
<div class="slide-container">
<div class="slide-items">
<div class="slide-item">one</div>



