transition、transform、keyframes 三件套,给交互加一点温度,又不喧宾夺主。
静态页面是冷的,加一点动效就能让它活过来。但动效不是为了炫技,而是给用户的操作一个明确回应:按钮按下有反馈、卡片悬停会被强调、内容入场有节奏。这一课我们用 CSS 原生的 transition、transform、keyframes 三件套,做出克制又好用的微动效。
动手写之前先想清楚动效在解决什么问题。好的动效通常只做两件事:
凡是没服务于这两件事的动效,多半是噪音。新手最容易犯的错就是“什么都加动效”,结果页面晃来晃去,反而分散注意力。
transition 是最基础的动效,让某个属性从 A 值平滑过渡到 B 值。它需要一个触发条件(比如 :hover),否则属性是瞬间变化的。
.btn {
background: #7FB069;
color: #fff;
/* 监听 background 和 transform,过渡 0.3s,缓动 ease */
transition: background 0.3s ease, transform 0.3s ease;
}
.btn:hover {
background: #4A7C3A;
transform: translateY(-2px);
}
简写顺序是 transition: 属性 时长 缓动 延迟。常用属性可以一次写多个,也可以用 transition: all 0.3s ease,但不推荐——只过渡真正需要的属性,性能更可控。
/* 更推荐的写法:明确属性 */
.card {
transition:
transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
box-shadow 0.35s ease;
}
缓动函数里 ease 适合大多数场景,cubic-bezier(0.34, 1.56, 0.64, 1) 带“回弹”,适合按钮、卡片这类需要俏皮感的元素。匀速 linear 反而少用,看着很机械。
transform 用来移动、缩放、旋转、倾斜元素,最关键的是:它不会触发布局重排,性能远好于改 top/left/width/margin。动画里能用 transform 就别用布局属性。
.icon {
transition: transform 0.3s ease;
}
/* 悬停时图标向右挪一点 */
.icon:hover {
transform: translateX(4px);
}
/* 缩放:常用于卡片强调 */
.card:hover { transform: scale(1.05); }
/* 旋转:常用于图标、加载 */
.spinner { transform: rotate(180deg); }
/* 组合:位移 + 缩放 */
.btn:active { transform: translateY(1px) scale(0.98); }
transform 还有个好搭档 transform-origin,控制变换的“支点”。默认是元素中心,做翻牌、扇形展开时改成角落会更自然:
.flag {
transform-origin: left center;
transition: transform 0.4s ease;
}
.flag:hover { transform: rotate(-8deg); }
把前两节合起来,写两个最常见的微动效。第一个是按钮:悬停上浮、按下下沉。
.btn {
padding: 13px 30px;
background: linear-gradient(135deg, #A8D5BA, #7FB069);
color: #fff;
border-radius: 999px;
box-shadow: 0 2px 8px rgba(74, 124, 58, 0.04);
transition:
transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
box-shadow 0.3s ease;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 36px rgba(74, 124, 58, 0.10);
}
.btn:active {
transform: translateY(0) scale(0.98);
}
第二个是卡片:悬停时整体上浮、图片轻微放大。注意图片的 scale 要单独写,并配合 overflow:hidden 裁剪溢出。
.card {
overflow: hidden;
border-radius: 24px;
transition:
transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
box-shadow 0.4s ease;
}
.card:hover {
transform: translateY(-10px);
box-shadow: 0 24px 60px rgba(74, 124, 58, 0.14);
}
.card img {
transition: transform 0.6s ease;
}
.card:hover img {
transform: scale(1.06);
}
transition 只能在两个状态间过渡,需要持续或循环的动画时,用 @keyframes 定义关键帧,再用 animation 应用。下面是一个加载圈:
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
width: 32px;
height: 32px;
border: 3px solid #E4F0DC;
border-top-color: #7FB069;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
animation 的简写顺序:animation: 名称 时长 缓动 延迟 次数 方向。常用组合:
/* 入场:从下淡入,只播一次,停留在末态 */
@keyframes fadeUp {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}
.reveal {
opacity: 0;
animation: fadeUp 0.8s ease forwards;
}
/* 呼吸:缩放在 1 和 1.08 之间来回,无限循环 */
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.08); }
}
.dot { animation: pulse 1.6s ease-in-out infinite; }
动效写得越多越容易翻车,性能上也有代价。几条经验:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
这是动效的无障碍底线:让需要安静的用户得到安静。加这一段,你的动效才算真正合格。
到这里,基础教程的五篇就串起来了:HTML 搭骨架、CSS 穿样式、布局排版、响应式适配、动效加温度。把它们练熟,你已经能独立做出一个像样的网页。接下来可以挑感兴趣的方向继续深入,配色、版式、工具,哪一块都值得慢慢磨。