Appearance
动画与过渡
CSS 动画和过渡可以让网页元素产生动态效果,提升用户体验。
过渡(Transition)
过渡用于在两个状态之间平滑切换。
基本语法
css
.element {
transition: property duration timing-function delay;
}transition-property
指定要过渡的属性:
css
div {
transition-property: all; /* 所有属性 */
transition-property: width; /* 单个属性 */
transition-property: width, height, background-color; /* 多个属性 */
}transition-duration
设置过渡时间:
css
div {
transition-duration: 0.3s;
transition-duration: 300ms;
transition-duration: 0.3s, 0.5s; /* 多个属性对应不同时间 */
}transition-timing-function
设置过渡速度曲线:
css
div {
transition-timing-function: ease; /* 慢-快-慢(默认) */
transition-timing-function: linear; /* 匀速 */
transition-timing-function: ease-in; /* 慢开始 */
transition-timing-function: ease-out; /* 慢结束 */
transition-timing-function: ease-in-out; /* 慢开始和结束 */
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); /* 自定义 */
}transition-delay
设置过渡延迟:
css
div {
transition-delay: 0.5s;
}transition 简写
css
div {
transition: all 0.3s ease 0s;
transition: width 0.3s, height 0.5s ease-in-out;
}过渡示例
css
.button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
transition: background-color 0.3s ease, transform 0.2s ease;
}
.button:hover {
background-color: #0056b3;
transform: scale(1.05);
}变换(Transform)
变换用于对元素进行旋转、缩放、倾斜、移动。
2D 变换
translate(移动)
css
div {
transform: translate(50px, 100px); /* x, y */
transform: translateX(50px);
transform: translateY(100px);
}scale(缩放)
css
div {
transform: scale(2); /* 放大2倍 */
transform: scale(0.5); /* 缩小一半 */
transform: scale(2, 1.5); /* x, y 分别缩放 */
transform: scaleX(2);
transform: scaleY(1.5);
}rotate(旋转)
css
div {
transform: rotate(45deg); /* 顺时针旋转45度 */
transform: rotate(-45deg); /* 逆时针旋转 */
}skew(倾斜)
css
div {
transform: skew(10deg, 20deg); /* x, y 倾斜 */
transform: skewX(10deg);
transform: skewY(20deg);
}matrix(矩阵)
css
div {
transform: matrix(1, 0, 0, 1, 0, 0);
}3D 变换
translate3d
css
div {
transform: translate3d(50px, 100px, 200px);
transform: translateZ(100px);
}scale3d
css
div {
transform: scale3d(1, 1.5, 2);
transform: scaleZ(2);
}rotate3d
css
div {
transform: rotate3d(1, 1, 1, 45deg);
transform: rotateX(45deg);
transform: rotateY(45deg);
transform: rotateZ(45deg);
}perspective(透视)
css
.parent {
perspective: 1000px; /* 透视距离 */
}
.child {
transform: rotateY(45deg);
}transform-style
css
.parent {
transform-style: flat; /* 2D(默认) */
transform-style: preserve-3d; /* 3D */
}backface-visibility
css
div {
backface-visibility: visible; /* 背面可见(默认) */
backface-visibility: hidden; /* 背面隐藏 */
}transform-origin
设置变换原点:
css
div {
transform-origin: center center; /* 默认 */
transform-origin: top left;
transform-origin: 50% 50%;
transform-origin: 20px 30px;
}关键帧动画(Animation)
关键帧动画可以创建更复杂的动画序列。
@keyframes
定义动画关键帧:
css
@keyframes slideIn {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* 或使用百分比 */
@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-30px);
}
}animation 属性
animation-name
指定动画名称:
css
div {
animation-name: slideIn;
}animation-duration
设置动画时间:
css
div {
animation-duration: 1s;
}animation-timing-function
设置动画速度曲线:
css
div {
animation-timing-function: ease;
animation-timing-function: linear;
animation-timing-function: ease-in-out;
animation-timing-function: steps(5, end);
}animation-delay
设置动画延迟:
css
div {
animation-delay: 0.5s;
}animation-iteration-count
设置动画次数:
css
div {
animation-iteration-count: 1; /* 播放1次 */
animation-iteration-count: 3; /* 播放3次 */
animation-iteration-count: infinite; /* 无限循环 */
}animation-direction
设置动画方向:
css
div {
animation-direction: normal; /* 正向(默认) */
animation-direction: reverse; /* 反向 */
animation-direction: alternate; /* 正反交替 */
animation-direction: alternate-reverse; /* 反正交替 */
}animation-fill-mode
设置动画填充模式:
css
div {
animation-fill-mode: none; /* 默认 */
animation-fill-mode: forwards; /* 保持结束状态 */
animation-fill-mode: backwards; /* 保持开始状态 */
animation-fill-mode: both; /* 两端都保持 */
}animation-play-state
设置动画播放状态:
css
div {
animation-play-state: running; /* 播放(默认) */
animation-play-state: paused; /* 暂停 */
}animation 简写
css
div {
animation: name duration timing-function delay iteration-count direction fill-mode;
animation: slideIn 1s ease 0s 1 normal forwards;
animation: bounce 0.5s ease-in-out infinite alternate;
}常用动画效果
淡入淡出
css
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}弹跳效果
css
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
.bounce {
animation: bounce 1s ease infinite;
}旋转加载
css
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinner {
animation: spin 1s linear infinite;
}脉冲效果
css
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.pulse {
animation: pulse 1s ease-in-out infinite;
}摇晃效果
css
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
20%, 40%, 60%, 80% { transform: translateX(10px); }
}
.shake {
animation: shake 0.5s ease-in-out;
}性能优化
使用 transform 和 opacity
这两个属性不会触发重排,性能更好:
css
/* 推荐 */
.element {
transition: transform 0.3s, opacity 0.3s;
}
.element:hover {
transform: scale(1.1);
opacity: 0.8;
}
/* 不推荐 */
.element {
transition: width 0.3s, height 0.3s, left 0.3s, top 0.3s;
}will-change
提示浏览器将要变化的属性:
css
.element {
will-change: transform, opacity;
}实践示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>动画与过渡示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
}
h2 {
margin: 30px 0 15px;
color: #333;
}
/* 过渡按钮 */
.btn {
padding: 12px 24px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;
margin: 5px;
}
.btn-primary {
background-color: #007bff;
color: white;
}
.btn-primary:hover {
background-color: #0056b3;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.4);
}
.btn-outline {
background-color: transparent;
color: #007bff;
border: 2px solid #007bff;
}
.btn-outline:hover {
background-color: #007bff;
color: white;
}
/* 卡片悬停 */
.card {
background: white;
border-radius: 8px;
padding: 20px;
margin: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
.cards {
display: flex;
flex-wrap: wrap;
}
/* 加载动画 */
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #007bff;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 20px auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 脉冲效果 */
.pulse-box {
width: 100px;
height: 100px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 50%;
margin: 20px auto;
animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.1); opacity: 0.8; }
}
/* 弹跳效果 */
.bounce-box {
width: 60px;
height: 60px;
background-color: #28a745;
border-radius: 8px;
margin: 20px auto;
animation: bounce 1s ease infinite;
}
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-20px); }
}
/* 3D 翻转 */
.flip-container {
perspective: 1000px;
width: 200px;
height: 120px;
margin: 20px auto;
}
.flip-card {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
transition: transform 0.6s;
}
.flip-container:hover .flip-card {
transform: rotateY(180deg);
}
.flip-front, .flip-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: bold;
}
.flip-front {
background: #007bff;
color: white;
}
.flip-back {
background: #28a745;
color: white;
transform: rotateY(180deg);
}
/* 淡入动画 */
.fade-in {
animation: fadeIn 1s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head>
<body>
<div class="container">
<h1>动画与过渡示例</h1>
<h2>按钮过渡效果</h2>
<button class="btn btn-primary">主要按钮</button>
<button class="btn btn-outline">轮廓按钮</button>
<h2>卡片悬停效果</h2>
<div class="cards">
<div class="card">
<h3>卡片 1</h3>
<p>悬停查看效果</p>
</div>
<div class="card">
<h3>卡片 2</h3>
<p>悬停查看效果</p>
</div>
<div class="card">
<h3>卡片 3</h3>
<p>悬停查看效果</p>
</div>
</div>
<h2>加载动画</h2>
<div class="spinner"></div>
<h2>脉冲效果</h2>
<div class="pulse-box"></div>
<h2>弹跳效果</h2>
<div class="bounce-box"></div>
<h2>3D 翻转效果</h2>
<div class="flip-container">
<div class="flip-card">
<div class="flip-front">正面</div>
<div class="flip-back">背面</div>
</div>
</div>
</div>
</body>
</html>