变换与动画
变换和动画是创建动态、交互式界面的关键。Tailwind CSS 提供了完整的变换工具类和动画支持,让你能够轻松创建各种视觉效果。本章将详细介绍如何使用这些工具类。
变换基础
变换包括缩放、旋转、倾斜和平移,可以改变元素的外观而不影响文档流。
变换原点
使用 origin-{position} 设置变换的原点:
<div class="origin-center rotate-45">中心点旋转(默认)</div>
<div class="origin-top rotate-45">顶部中心旋转</div>
<div class="origin-top-right rotate-45">右上角旋转</div>
<div class="origin-right rotate-45">右侧中心旋转</div>
<div class="origin-bottom-right rotate-45">右下角旋转</div>
<div class="origin-bottom rotate-45">底部中心旋转</div>
<div class="origin-bottom-left rotate-45">左下角旋转</div>
<div class="origin-left rotate-45">左侧中心旋转</div>
<div class="origin-top-left rotate-45">左上角旋转</div>
缩放
使用 scale-{value} 缩放元素:
统一缩放
<div class="scale-50">缩小到 50%</div>
<div class="scale-75">缩小到 75%</div>
<div class="scale-90">缩小到 90%</div>
<div class="scale-95">缩小到 95%</div>
<div class="scale-100">原始大小(默认)</div>
<div class="scale-105">放大到 105%</div>
<div class="scale-110">放大到 110%</div>
<div class="scale-125">放大到 125%</div>
<div class="scale-150">放大到 150%</div>
负值缩放
负值缩放会翻转元素:
<div class="-scale-50">翻转并缩小到 50%</div>
<div class="-scale-100">水平翻转</div>
<div class="-scale-y-100">垂直翻转</div>
分轴缩放
<div class="scale-x-50">水平方向缩小到 50%</div>
<div class="scale-x-150">水平方向放大到 150%</div>
<div class="scale-y-50">垂直方向缩小到 50%</div>
<div class="scale-y-150">垂直方向放大到 150%</div>
悬停缩放效果
<button class="hover:scale-105 active:scale-95 transition-transform duration-200 bg-blue-500 text-white px-4 py-2 rounded">
点击缩放
</button>
<div class="group">
<img src="image.jpg" class="group-hover:scale-110 transition-transform duration-300" alt="">
</div>
旋转
使用 rotate-{angle} 旋转元素:
<div class="rotate-0">不旋转</div>
<div class="rotate-1">旋转 1 度</div>
<div class="rotate-2">旋转 2 度</div>
<div class="rotate-3">旋转 3 度</div>
<div class="rotate-6">旋转 6 度</div>
<div class="rotate-12">旋转 12 度</div>
<div class="rotate-45">旋转 45 度</div>
<div class="rotate-90">旋转 90 度</div>
<div class="rotate-180">旋转 180 度</div>
负值旋转
<div class="-rotate-45">逆时针旋转 45 度</div>
<div class="-rotate-90">逆时针旋转 90 度</div>
任意角度
<div class="rotate-[23deg]">旋转 23 度</div>
<div class="rotate-[0.5turn]">旋转半圈</div>
旋转图标示例
<button class="group flex items-center gap-2">
<svg class="w-5 h-5 group-hover:rotate-180 transition-transform duration-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
刷新
</button>
平移
使用 translate-{direction}-{value} 移动元素:
水平移动
<div class="translate-x-0">不移动</div>
<div class="translate-x-1">向右移动 0.25rem</div>
<div class="translate-x-2">向右移动 0.5rem</div>
<div class="translate-x-4">向右移动 1rem</div>
<div class="translate-x-8">向右移动 2rem</div>
<div class="-translate-x-4">向左移动 1rem</div>
垂直移动
<div class="translate-y-0">不移动</div>
<div class="translate-y-1">向下移动 0.25rem</div>
<div class="translate-y-2">向下移动 0.5rem</div>
<div class="translate-y-4">向下移动 1rem</div>
<div class="-translate-y-4">向上移动 1rem</div>
百分比移动
<div class="translate-x-1/2">向右移动自身宽度的 50%</div>
<div class="translate-x-full">向右移动自身宽度</div>
<div class="-translate-x-full">向左移动自身宽度</div>
<div class="translate-y-1/2">向下移动自身高度的 50%</div>
居中定位技巧
<div class="relative h-64">
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
水平垂直居中
</div>
</div>
倾斜
使用 skew-{axis}-{angle} 倾斜元素:
<div class="skew-x-0">不倾斜</div>
<div class="skew-x-3">水平倾斜 3 度</div>
<div class="skew-x-6">水平倾斜 6 度</div>
<div class="skew-x-12">水平倾斜 12 度</div>
<div class="-skew-x-12">水平反向倾斜 12 度</div>
<div class="skew-y-0">不倾斜</div>
<div class="skew-y-3">垂直倾斜 3 度</div>
<div class="skew-y-6">垂直倾斜 6 度</div>
<div class="skew-y-12">垂直倾斜 12 度</div>
倾斜卡片效果
<div class="group perspective-1000">
<div class="transform group-hover:skew-x-3 group-hover:scale-105 transition duration-300 bg-white p-6 rounded-lg shadow-lg">
悬停倾斜
</div>
</div>
组合变换
多个变换可以组合使用:
<div class="scale-110 rotate-3 translate-x-2">
组合变换效果
</div>
<button class="hover:scale-105 hover:-translate-y-1 hover:shadow-lg transition-all duration-200 bg-blue-500 text-white px-4 py-2 rounded">
悬停上浮效果
</button>
移除变换
<div class="scale-75 translate-x-4 skew-y-3 md:transform-none">
在 md 断点移除所有变换
</div>
动画
Tailwind CSS 内置了多个常用动画,也支持自定义动画。
内置动画
旋转动画:
<svg class="animate-spin h-5 w-5 text-blue-500" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
脉冲动画(扩散效果):
<span class="relative flex h-3 w-3">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75"></span>
<span class="relative inline-flex rounded-full h-3 w-3 bg-sky-500"></span>
</span>
闪烁动画(淡入淡出):
<div class="animate-pulse bg-gray-200 h-4 w-3/4 rounded"></div>
<div class="animate-pulse bg-gray-200 h-4 w-1/2 rounded mt-2"></div>
<div class="animate-pulse bg-gray-200 h-4 w-5/6 rounded mt-2"></div>
弹跳动画:
<svg class="animate-bounce w-6 h-6 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" />
</svg>
自定义动画
在 CSS 中使用 @theme 定义自定义动画:
@import "tailwindcss";
@theme {
--animate-fade-in: fade-in 0.5s ease-out;
--animate-slide-up: slide-up 0.3s ease-out;
--animate-bounce-in: bounce-in 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slide-up {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes bounce-in {
0% { transform: scale(0.3); opacity: 0; }
50% { transform: scale(1.05); }
70% { transform: scale(0.9); }
100% { transform: scale(1); opacity: 1; }
}
}
使用自定义动画:
<div class="animate-fade-in">淡入效果</div>
<div class="animate-slide-up">滑入效果</div>
<div class="animate-bounce-in">弹跳进入</div>
任意动画值
<div class="animate-[wiggle_1s_ease-in-out_infinite]">摇摆动画</div>
无障碍动画
尊重用户的减少动画偏好设置:
<button class="motion-safe:animate-spin">
仅在允许动画时旋转
</button>
<button class="motion-reduce:animate-none">
在减少动画设置下禁用动画
</button>
推荐做法:
<button class="animate-spin motion-reduce:animate-none">
默认旋转,减少动画时禁用
</button>
过渡效果
过渡让状态变化更加平滑自然。
过渡属性
<div class="transition">过渡所有属性</div>
<div class="transition-none">无过渡</div>
<div class="transition-all">过渡所有属性</div>
<div class="transition-colors">仅过渡颜色</div>
<div class="transition-opacity">仅过渡透明度</div>
<div class="transition-shadow">仅过渡阴影</div>
<div class="transition-transform">仅过渡变换</div>
过渡时长
<div class="duration-75">75ms</div>
<div class="duration-100">100ms</div>
<div class="duration-150">150ms</div>
<div class="duration-200">200ms</div>
<div class="duration-300">300ms</div>
<div class="duration-500">500ms</div>
<div class="duration-700">700ms</div>
<div class="duration-1000">1000ms</div>
过渡延迟
<div class="delay-75">延迟 75ms</div>
<div class="delay-150">延迟 150ms</div>
<div class="delay-300">延迟 300ms</div>
<div class="delay-500">延迟 500ms</div>
<div class="delay-700">延迟 700ms</div>
<div class="delay-1000">延迟 1000ms</div>
过渡曲线
<div class="ease-linear">线性过渡</div>
<div class="ease-in">加速过渡</div>
<div class="ease-out">减速过渡</div>
<div class="ease-in-out">先加速后减速</div>
任意曲线
<div class="ease-[cubic-bezier(0.68,-0.55,0.265,1.55)]">
自定义贝塞尔曲线
</div>
实战示例
按钮交互
<button class="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 hover:scale-105 active:scale-95 text-white font-medium px-6 py-3 rounded-lg shadow-lg hover:shadow-xl transition-all duration-200">
完整交互按钮
</button>
卡片悬停效果
<div class="group bg-white rounded-xl shadow-md hover:shadow-2xl transition-all duration-300 overflow-hidden">
<div class="overflow-hidden">
<img src="image.jpg" class="group-hover:scale-110 transition-transform duration-500" alt="">
</div>
<div class="p-6">
<h3 class="font-bold text-lg group-hover:text-blue-500 transition-colors">卡片标题</h3>
<p class="text-gray-600 mt-2">卡片描述内容</p>
</div>
</div>
加载按钮
<button class="relative bg-blue-500 text-white px-6 py-3 rounded-lg disabled:opacity-75" disabled>
<span class="flex items-center justify-center gap-2">
<svg class="animate-spin h-5 w-5" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
</svg>
处理中...
</span>
</button>
抽屉动画
<div class="fixed inset-y-0 right-0 w-64 bg-white shadow-xl transform translate-x-full transition-transform duration-300" id="drawer">
<div class="p-6">
<h2 class="text-xl font-bold">侧边栏</h2>
<p class="mt-4 text-gray-600">这是一个从右侧滑入的抽屉</p>
</div>
</div>
<!-- 打开时移除 translate-x-full -->
<div class="transform translate-x-0">
打开状态
</div>
模态框动画
<!-- 遮罩层 -->
<div class="fixed inset-0 bg-black/50 backdrop-blur-sm opacity-0 transition-opacity duration-300">
</div>
<!-- 模态框 -->
<div class="fixed inset-0 flex items-center justify-center">
<div class="bg-white rounded-xl shadow-2xl p-6 transform scale-95 opacity-0 transition-all duration-300">
<h2 class="text-xl font-bold">模态框</h2>
<p class="mt-2 text-gray-600">内容区域</p>
</div>
</div>
<!-- 打开状态 -->
<!-- 遮罩: opacity-100 -->
<!-- 模态框: scale-100 opacity-100 -->
下拉菜单
<div class="relative">
<button class="bg-blue-500 text-white px-4 py-2 rounded">
菜单
</button>
<div class="absolute top-full left-0 mt-2 w-48 bg-white rounded-lg shadow-lg opacity-0 scale-95 -translate-y-2 pointer-events-none transition-all duration-200">
<a href="#" class="block px-4 py-2 hover:bg-gray-100">选项 1</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-100">选项 2</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-100">选项 3</a>
</div>
</div>
<!-- 打开状态 -->
<!-- opacity-100 scale-100 translate-y-0 pointer-events-auto -->
交错动画
<div class="space-y-2">
<div class="animate-[slide-up_0.5s_ease-out_forwards] animation-delay-100 opacity-0">项目 1</div>
<div class="animate-[slide-up_0.5s_ease-out_forwards] animation-delay-200 opacity-0">项目 2</div>
<div class="animate-[slide-up_0.5s_ease-out_forwards] animation-delay-300 opacity-0">项目 3</div>
<div class="animate-[slide-up_0.5s_ease-out_forwards] animation-delay-400 opacity-0">项目 4</div>
</div>
3D 卡片翻转
<div class="perspective-1000">
<div class="relative w-64 h-40 transition-transform duration-500 transform-style-3d hover:rotate-y-180">
<!-- 正面 -->
<div class="absolute inset-0 backface-hidden bg-blue-500 rounded-lg flex items-center justify-center text-white">
正面
</div>
<!-- 背面 -->
<div class="absolute inset-0 backface-hidden bg-gray-800 rounded-lg flex items-center justify-center text-white rotate-y-180">
背面
</div>
</div>
</div>
小结
本章介绍了 Tailwind CSS 的变换与动画工具类:
- 缩放:使用
scale-{value}缩放元素,支持分轴缩放 - 旋转:使用
rotate-{angle}旋转元素 - 平移:使用
translate-{direction}-{value}移动元素 - 倾斜:使用
skew-{axis}-{angle}倾斜元素 - 变换原点:使用
origin-{position}设置变换中心点 - 内置动画:spin、ping、pulse、bounce
- 自定义动画:使用
@theme定义关键帧动画 - 过渡效果:控制过渡属性、时长、延迟和曲线
- 无障碍:使用
motion-safe和motion-reduce尊重用户偏好
下一章,我们将学习状态样式的使用方法。