CSS3:从 2D 变换到 3D 翻转

在前端开发中,页面动效是区分 "普通页面" 和 "精致页面" 的关键。这篇文章整理了从最基础的 2D 位移到炫酷的 3D 卡片翻转的的基础内容。

一、2D 变换

CSS 动效的核心是transform属性,它不会改变元素在文档流中的位置,也不会影响其他元素的布局,这是它比position、margin更适合做动效的根本原因。2D 变换包含 4 个最常用的基础能力,每个都有自己的典型应用场景:

1. 四大基础变换详解

  • 位移translate(x, y) :最常用的动效属性,实现元素的水平 / 垂直移动。translateX()只控制水平方向,translateY()只控制垂直方向。

    • 典型应用:按钮悬停上移、导航下拉、卡片悬浮效果

    • 注意:百分比值是相对于元素自身宽高 计算的,这也是用它实现 "水平垂直居中" 的原理:transform: translate(-50%, -50%)

  • 旋转rotate(deg):让元素绕中心点旋转,单位是度 (deg)。正值顺时针旋转,负值逆时针旋转。

    • 典型应用:箭头旋转、图标翻转、加载动画

    • 进阶技巧:通过transform-origin自定义旋转中心,比如transform-origin: left top可以让元素绕左上角旋转

  • 缩放scale(n) :让元素放大或缩小,值小于 1 为缩小,大于 1 为放大。scaleX()和scaleY()可以分别控制水平和垂直方向的缩放。

    • 典型应用:图片悬停放大、按钮点击缩小反馈

    • 注意:缩放不会改变元素的实际占位,所以不会导致页面布局抖动

  • 倾斜skew(xdeg, ydeg):让元素沿 X 轴或 Y 轴倾斜,适合做一些有设计感的效果。

    • 典型应用:斜切按钮、倾斜卡片、创意文字效果

2. 组合变换的执行顺序

transform 的多个变换是从右往左执行的。

css 复制代码
/* 先向右移动100px,再旋转45度 */
transform: translate(100px) rotate(45deg);

/* 先旋转45度,再沿着旋转后的X轴向右移动100px */
transform: rotate(45deg) translate(100px);

这两行代码的效果完全不同,因为旋转会带着元素的坐标系一起转动。

二、3D 变换

2D 变换只能在平面上操作,而 3D 变换能让元素在三维空间中运动,做出非常有冲击力的效果。实现 3D 效果离不开三个核心属性:

1. 3D 变换三大基础操作

  1. 透视perspective:加在父元素上,模拟人眼到屏幕的距离,值越小,3D 效果越明显。一般设置在 500px-1000px 之间比较自然。

    两种写法对比:

    • 父元素加perspective: 1000px:所有子元素共享同一个透视点,效果更真实
    • 子元素加transform: perspective(1000px):每个子元素有自己的透视点
  2. 保留 3D 空间transform-style: preserve-3d:必须加在父元素上,让子元素继承父级的 3D 环境。如果不加这个属性,所有子元素都会被压平在父元素的平面上,看不到 3D 效果。

  3. 背面隐藏backface-visibility: hidden:3D 翻转时隐藏元素的背面,避免出现 "穿模" 的尴尬情况。

2. 案例:两面翻转图片

这是 3D 变换最常用的效果,核心代码非常简洁,可以直接复用在名片、商品卡片、相册等场景:

css 复制代码
/* 父容器,添加透视 */
.flip-card {
  perspective: 1000px;
  width: 300px;
  height: 200px;
}

/* 卡片容器,负责翻转 */
.flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.6s ease;
}

/* 正反面公共样式 */
.flip-card-front, .flip-card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  border-radius: 8px;
}

/* 正面 */
.flip-card-front {
  background-color: #fff;
}

/* 背面,默认旋转180度隐藏 */
.flip-card-back {
  background-color: #2196F3;
  color: white;
  transform: rotateY(180deg);
}

/* hover时翻转整个卡片 */
.flip-card:hover .flip-card-inner {
  transform: rotateY(180deg);
}

三、CSS 动画

要分清transition和animation,记住这个核心区别:

  • transition:触发式过渡,需要 hover、点击、类名变化等事件触发,只能定义 "开始" 和 "结束" 两个状态,适合简单的状态变化
  • animation:关键帧动画 ,通过@keyframes定义任意多个中间状态,支持循环、反向、暂停等高级控制,适合复杂的、自动播放的动效

1. animation 完整属性

animation是一个简写属性,完整写法包含 8 个属性:

css 复制代码
animation: 动画名 时长 运动曲线 延迟 循环次数 播放方向 结束状态 播放状态;
  • 常用的运动曲线:ease(慢 - 快 - 慢)、linear(匀速)、ease-in(慢入)、ease-out(慢出)
  • 循环次数:infinite表示无限循环
  • 播放方向:alternate表示交替播放,动画会在结束后反向回到起点
  • 结束状态:forwards表示动画结束后停留在最后一帧

2. steps():实现逐帧动画

steps()函数可以将平滑的动画拆分为固定的步数,实现逐帧播放的效果。

  • 典型应用:精灵图动画、打字机效果、页面加载动画
css 复制代码
/* 10帧的精灵图动画,每帧停留0.1秒 */
@keyframes sprite {
  from { background-position: 0 0; }
  to { background-position: -1000px 0; }
}
.sprite {
  width: 100px;
  height: 100px;
  background: url(sprite.png) no-repeat;
  animation: sprite 1s steps(10) infinite;
}

四、汇总

  1. 行内元素不能用 transform :<span>、<a>等行内元素设置 transform 无效,需要先转为块级或行内块元素:display: inline-block
  2. transform 会提升元素层级:设置了 transform 的元素会比普通元素层级高,可能会覆盖其他元素
  3. 不要同时使用 transform 和 margin 做动效:margin 会触发页面重排,性能很差,所有动效都应该用 transform 实现
  4. 3D 变换中 z-index 失效 :在 3D 空间中,元素的层级由z-index和translateZ共同决定,translateZ值越大,元素越靠前
相关推荐
卸任19 小时前
Vibe coding工具使用心得
前端·ai编程
brien920 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance20 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M20 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写20 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李20 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易21 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马21 小时前
前沿视界
前端
kyriewen21 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易21 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员