一、过渡(transition):让元素“自然变化”的基础
过渡是CSS3中最常用的动效工具,它能让元素的CSS属性从一个值“平滑过渡”到另一个值,无需JS。核心语法是transition: [属性] [时长] [ timing 函数] [延迟]
,四个部分可以合并写,也能分开指定。

比如你想做一个按钮hover时背景色渐变,只需要这样写:
.btn {
background: #42b983;
color: #fff;
padding: 8px 16px;
border: none;
border-radius: 4px;
/* 过渡背景色,时长0.3秒,ease曲线 */
transition: background 0.3s ease;
}
.btn:hover {
background: #318a62; /* hover时的深色 */
}
这个例子里,transition
帮你完成了从浅绿到深绿的平滑变化,不用写任何JS。
过渡的“四要素”拆解
如果你想更精细控制,可以把transition
拆成四个单独属性:
| 属性 | 作用 | 示例 |
|———————|———————————–|——————|
| transition-property
| 要过渡的CSS属性(必填) | background
、transform
|
| transition-duration
| 过渡时长(必填,不能为0) | 0.3s
、500ms
|
| transition-timing-function
| 过渡的“速度曲线” | ease
(默认)、linear
(匀速)、ease-in-out
(慢快慢) |
| transition-delay
| 延迟多久开始过渡 | 0.1s
(延迟100ms) |
比如你想让按钮hover时,背景色和边框同时过渡,且延迟0.1秒:
.btn {
border: 2px solid #42b983;
transition-property: background, border;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0.1s;
}
.btn:hover {
background: #318a62;
border-color: #286e51;
}
二、动画(animation):让元素“自主运动”的高级工具
过渡适合“触发式”变化(比如hover、click),而动画(animation
)适合更复杂的“自主循环”动效,比如加载动画、轮播图。它需要两个核心部分:用@keyframes
定义“关键帧”(动画的不同阶段);用animation
属性把关键帧绑定到元素上。
第一步:写关键帧
比如要做一个“旋转的加载图标”,关键帧就是从0deg
转到360deg
:
/* 定义名为spin的关键帧 */
@keyframes spin {
from {
transform: rotate(0deg); /* 起始状态:0度 */
}
to {
transform: rotate(360deg); /* 结束状态:360度 */
}
}
或者用百分比定义多阶段:
@keyframes bounce {
0% { transform: translateY(0); } /* 开始在原点 */
50% { transform: translateY(-20px); } /* 中间弹起20px */
100% { transform: translateY(0); } /* 回到原点 */
}
第二步:绑定动画到元素
定义好关键帧后,用animation
属性把它“贴”到元素上:
.loader {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #42b983;
border-radius: 50%; /* 圆形 */
/* 绑定spin关键帧,时长1秒,匀速,无限循环 */
animation: spin 1s linear infinite;
}
这样就能得到一个无限旋转的加载图标,完全不需要JS!
动画的“进阶控制”
animation
还有很多实用属性,帮你调整动画的细节:
– animation-iteration-count
:循环次数(infinite
表示无限);
– animation-direction
:播放方向(alternate
表示“来回播放”,比如 bounce 动画);
– animation-fill-mode
:动画结束后保持状态(forwards
保持最后一帧,backwards
保持第一帧);
– animation-play-state
:控制播放/暂停(paused
暂停,running
播放)。
比如你想做一个“来回弹跳”的小球:
.ball {
width: 50px;
height: 50px;
background: #ff4444;
border-radius: 50%;
/* 绑定bounce关键帧,时长0.5秒,ease-in-out,无限来回 */
animation: bounce 0.5s ease-in-out infinite alternate;
}
@keyframes bounce {
from { transform: translateY(0); }
to { transform: translateY(-30px); }
}
这个小球会在“原点”和“上方30px”之间来回弹跳,很适合做提示动画。
三、动画的“动力源”:transform属性
不管是过渡还是动画,大部分动效都离不开transform
——它能让元素“位移、旋转、缩放、倾斜”,而且不会触发重排(性能更好)。
transform的“四大基本操作”
操作 | 语法 | 效果 |
---|---|---|
位移 | translateX(10px) 、translateY(-20px) |
水平/垂直移动 |
旋转 | rotate(10deg) |
顺时针旋转10度 |
缩放 | scale(1.2) |
放大1.2倍 |
倾斜 | skewX(10deg) |
水平倾斜10度 |
这些操作可以组合使用,比如让卡片hover时“放大+旋转”:
.card {
width: 200px;
height: 250px;
background: #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
/* 过渡transform,时长0.3秒 */
transition: transform 0.3s ease;
}
.card:hover {
/* 放大1.05倍,旋转3度 */
transform: scale(1.05) rotate(3deg);
box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* 增强阴影 */
}
这个效果很常见于产品卡片,能让交互更有层次感。
四、实战:用CSS3做“有温度”的交互特效
光看基础没用,我们来做几个真实场景的案例,帮你把知识变成技能。
案例1:导航栏的“滑下”下拉菜单
很多网站的导航栏hover时会弹出下拉菜单,用transition
就能做:
/* 导航项容器 */
.nav-item {
position: relative;
display: inline-block;
margin: 0 10px;
}
/* 下拉菜单样式 */
.dropdown {
position: absolute;
top: 100%; /* 导航项正下方 */
left: 0;
background: #fff;
border: 1px solid #eee;
padding: 8px 0;
min-width: 120px;
/* 初始状态:透明+隐藏 */
opacity: 0;
visibility: hidden;
/* 过渡opacity和visibility,时长0.3秒 */
transition: opacity 0.3s ease, visibility 0.3s ease;
}
/* hover时显示下拉菜单 */
.nav-item:hover .dropdown {
opacity: 1;
visibility: visible;
}
/* 下拉菜单项样式 */
.dropdown-item {
padding: 8px 16px;
color: #333;
text-decoration: none;
display: block;
}
.dropdown-item:hover {
background: #f5f5f5;
}
这里要注意:visibility
用来控制“点击ability”(透明时还是能点到,所以要加visibility: hidden
),而opacity
控制透明度——两者一起过渡,才能让菜单“自然滑下”。
案例2:滚动触发的“渐入”动画
很多网页滚动时,元素会“从下往上渐入”,这个效果可以用Intersection Observer
(JS)配合CSS动画实现:
首先写CSS动画:
/* 初始状态:透明+向下偏移20px */
.fade-in {
opacity: 0;
transform: translateY(20px);
/* 定义渐入动画,时长0.5秒,保持最后一帧 */
animation: fadeIn 0.5s ease forwards;
/* 默认暂停动画 */
animation-play-state: paused;
}
/* 当元素进入视口时,启动动画 */
.fade-in.visible {
animation-play-state: running;
}
/* 渐入关键帧 */
@keyframes fadeIn {
to {
opacity: 1;
transform: translateY(0);
}
}
然后用JS监听元素是否进入视口:
// 创建观察者:当元素进入视口时触发
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible'); // 加visible类,启动动画
observer.unobserve(entry.target); // 只触发一次
}
});
}, { threshold: 0.1 }); // 元素进入10%时触发
// 监听所有.fade-in元素
document.querySelectorAll('.fade-in').forEach(el => observer.observe(el));
这样,当用户滚动到元素时,它会“缓缓出现”,很适合做内容区的动画。
五、动效的“性能优化”:避免踩坑
动效做不好会“卡帧”,记住这几个技巧,让你的动效更流畅:
1. 优先用“ compositor 友好”的属性
尽量用transform
和opacity
做动效——它们会被浏览器的“ compositor 层”处理,不会触发重排/重绘。避免用left
、top
、width
、height
这些属性,它们会让浏览器重新计算布局(性能差)。
2. 用will-change提前“通知”浏览器
如果元素要做复杂动效,可以用will-change
告诉浏览器“这个元素要动了”,让浏览器提前准备:
.card {
will-change: transform; /* 告诉浏览器:这个元素要变transform了 */
transition: transform 0.3s ease;
}
注意:不要滥用will-change
,否则会占用过多内存。
3. 避免“过大的动画元素”
如果动画元素占满整个屏幕(比如背景动画),会增加GPU负担。尽量让动画元素“小而精”,比如图标、按钮、卡片。
4. 无限动画要“流畅循环”
如果做无限动画(比如加载图标),要确保keyframes
的“开始”和“结束”状态一致,避免“跳帧”。比如旋转动画的from
和to
要衔接:
/* 正确的旋转关键帧 */
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); } /* 360度刚好一圈,循环流畅 */
}
/* 错误的旋转关键帧(会跳帧) */
@keyframes badSpin {
from { transform: rotate(0deg); }
to { transform: rotate(359deg); } /* 差1度,循环时会闪一下 */
}
最后:动效的“设计原则”
做动效不是“越复杂越好”,记住这两点:
– 动效是“辅助”:比如按钮hover动效是为了提示“可点击”,加载动画是为了告诉用户“正在加载”——不要为了动而动;
– 保持一致性:整个页面的动效曲线(比如都是ease
)、时长(比如都是0.3秒)要统一,否则会显得“杂乱”。
现在,你已经掌握了CSS3动画与过渡的核心技巧——赶紧打开CodePen,试着做几个动效吧!比如:
1. 按钮的“按压”动画(用scale
缩小);
2. 图标の“旋转”动画(用rotate
);
3. 卡片の“翻转”动画(用transform: rotateY(180deg)
)。
动动手,你会发现CSS3动效其实没那么难~
原创文章,作者:,如若转载,请注明出处:https://zube.cn/archives/176