学习目标

  • 理解3D变换的核心概念(透视、3D空间、变换原点)
  • 掌握perspective属性的语法与取值规则
  • 实现基础3D变换效果(旋转、平移、缩放)
  • 掌握transform-style: preserve-3d的应用场景
  • 能够开发简单的3D交互效果(如卡片翻转、立方体展示)

概念讲解

3D变换是CSS3在2D变换基础上扩展的空间变换能力,通过模拟三维空间坐标系实现元素的立体效果。与2D变换相比,3D变换增加了Z轴维度,使元素能够在三维空间中进行旋转、平移和缩放。

核心术语

  • 三维坐标系:以元素左上角为原点,X轴(水平方向)、Y轴(垂直方向)、Z轴(垂直屏幕方向,正值向外)
  • 透视(Perspective):模拟人眼观察物体的"近大远小"效果,值越小透视感越强(默认无透视)
  • 变换样式(Transform Style):控制子元素是否继承3D空间(preserve-3d开启3D空间,flat默认平面)
  • 变换原点(Transform Origin):3D变换的基准点(默认元素中心,可通过transform-origin调整)

3D与2D变换的区别

特性 2D变换 3D变换
坐标系 X轴、Y轴 X轴、Y轴、Z轴
透视效果 需设置perspective属性
子元素空间 平面堆叠 可形成3D空间层次
典型属性 translate()rotate() translate3d()rotateX()

语法参考

1. 透视属性(perspective

定义3D空间的透视距离,决定元素的立体感强度。可应用于父容器(影响所有子元素)或自身(仅影响自身)。

语法 取值 描述
perspective: none 默认值,无透视效果 元素以2D方式渲染
perspective: 数值+单位 500px800px 数值越小,透视效果越强

示例

/* 父容器设置透视,影响所有子元素 */
.container {
  perspective: 800px; /* 透视距离800px */
}

/* 子元素应用3D变换 */
.box {
  transform: rotateY(45deg); /* 沿Y轴旋转45度 */
}

2. 3D变换属性(transform

在2D变换基础上新增3D专属函数,支持Z轴变换:

函数 作用 示例
translate3d(x, y, z) 3D平移(Z轴正值向外) translate3d(50px, 20px, 100px)
rotateX(angle) 沿X轴旋转(上下翻转) rotateX(45deg)
rotateY(angle) 沿Y轴旋转(左右翻转) rotateY(45deg)
rotateZ(angle) 沿Z轴旋转(平面旋转,同2D rotate rotateZ(30deg)
scale3d(x, y, z) 3D缩放(Z轴缩放影响厚度感) scale3d(1.2, 1.2, 1.5)
perspective(n) 单个元素设置透视(仅影响自身) transform: perspective(500px) rotateY(30deg)

3. 3D空间样式(transform-style

控制子元素是否处于3D空间中,必须设置在父元素上。

取值 效果
flat 默认值,子元素在平面上渲染
preserve-3d 子元素保持3D空间关系,可相互遮挡

示例

.parent {
  transform-style: preserve-3d; /* 开启3D空间 */
  transform: rotateX(30deg);
}

.child {
  transform: translateZ(50px); /* 子元素沿Z轴平移,形成层次感 */
}

4. 背面可见性(backface-visibility

控制元素旋转后背面是否可见(常用于卡片翻转效果)。

取值 效果
visible 默认值,背面可见
hidden 背面不可见(透明)

示例

.card {
  backface-visibility: hidden; /* 旋转后背面隐藏 */
  transform-style: preserve-3d;
}

.card:hover {
  transform: rotateY(180deg); /* 翻转后显示正面 */
}

实战示例

示例1:基础3D旋转效果

实现沿Y轴旋转的立方体效果,包含透视设置和3D空间开启。

<div class="perspective-container">
  <div class="cube">
    <div class="cube-face front">前</div>
    <div class="cube-face back">后</div>
    <div class="cube-face left">左</div>
    <div class="cube-face right">右</div>
    <div class="cube-face top">上</div>
    <div class="cube-face bottom">下</div>
  </div>
</div>

<style>
/* 透视容器 */
.perspective-container {
  perspective: 1000px; /* 透视距离1000px */
  width: 200px;
  height: 200px;
  margin: 100px auto;
}

/* 立方体容器 */
.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d; /* 开启3D空间 */
  transform: rotateX(30deg) rotateY(45deg); /* 初始旋转角度 */
  transition: transform 1s ease;
}

/* 立方体每个面 */
.cube-face {
  position: absolute;
  width: 200px;
  height: 200px;
  border: 2px solid #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: bold;
  opacity: 0.8;
}

/* 面定位(基于正方体中心) */
.front  { background: #ff6b6b; transform: translateZ(100px); }
.back   { background: #4ecdc4; transform: translateZ(-100px) rotateY(180deg); }
.left   { background: #ffd166; transform: translateX(-100px) rotateY(-90deg); }
.right  { background: #06d6a0; transform: translateX(100px) rotateY(90deg); }
.top    { background: #118ab2; transform: translateY(-100px) rotateX(90deg); }
.bottom { background: #073b4c; transform: translateY(100px) rotateX(-90deg); }

/* 鼠标悬停效果 */
.cube:hover {
  transform: rotateX(30deg) rotateY(405deg); /* 旋转一周+45度 */
}
</style>

效果说明:

  • 父容器.perspective-container设置perspective: 1000px提供透视环境
  • .cube通过transform-style: preserve-3d开启3D空间,使6个子元素(面)处于同一3D坐标系
  • 每个面通过translateZ/X/Y定位到正方体的6个面,结合旋转形成立方体结构
  • 悬停时沿Y轴旋转360度+45度,展示3D空间效果

示例2:3D卡片翻转效果

实现鼠标悬停时卡片沿Y轴翻转,显示背面内容。

<div class="card-container">
  <div class="card">
    <div class="card-front">
      <h3>前端开发</h3>
      <p>点击翻转查看技能</p>
    </div>
    <div class="card-back">
      <ul>
        <li>HTML5语义化</li>
        <li>CSS3动画</li>
        <li>3D变换</li>
      </ul>
    </div>
  </div>
</div>

<style>
.card-container {
  perspective: 800px; /* 透视容器 */
  width: 300px;
  height: 200px;
  margin: 50px auto;
}

.card {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d; /* 开启3D空间 */
  transition: transform 0.6s; /* 翻转过渡 */
  cursor: pointer;
}

/* 卡片正反面 */
.card-front, .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden; /* 背面隐藏 */
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}

.card-front {
  background: linear-gradient(135deg, #4ecdc4, #556270);
  color: white;
}

.card-back {
  background: linear-gradient(135deg, #ff6b6b, #ffd166);
  color: #333;
  transform: rotateY(180deg); /* 初始背面翻转180度 */
}

/* 鼠标悬停翻转 */
.card-container:hover .card {
  transform: rotateY(180deg); /* 沿Y轴翻转180度 */
}
</style>

关键技术点:

  • backface-visibility: hidden确保卡片翻转时只显示当前面
  • 背面初始状态rotateY(180deg),悬停时父元素触发rotateY(180deg)实现翻转
  • transform-style: preserve-3d保证正反面在同一3D空间,避免平面重叠

注意事项

1. 浏览器兼容性

  • IE支持:IE10+部分支持3D变换,但不支持preserve-3d,需使用transform: matrix3d()手动计算矩阵

  • 移动端:iOS Safari 9.1+、Android Chrome 43+完全支持,低版本可能存在透视异常

  • 前缀

    :部分老浏览器需添加

    -webkit-
    

    前缀(如Safari 8-、Android Browser 4.4-):

    .element {
      -webkit-perspective: 800px;
      perspective: 800px;
      -webkit-transform-style: preserve-3d;
      transform-style: preserve-3d;
    }
    

2. 性能优化

  • 避免过度使用:3D变换(尤其是动画)会触发GPU加速,过多元素同时动画可能导致性能问题
  • 简化3D场景:复杂3D场景(如多个嵌套3D元素)建议使用will-change: transform提示浏览器优化
  • 控制透视距离perspective值不宜过小(< 200px),否则可能导致元素变形失真

3. 常见问题解决

问题 原因 解决方案
子元素3D效果不生效 未设置transform-style: preserve-3d 在父元素添加该属性
透视效果不明显 perspective值过大或未设置 减小perspective值(如500-1000px)
元素翻转后背面可见 未设置backface-visibility: hidden 在元素添加该属性
移动端卡顿 GPU加速导致内存占用过高 减少同时动画的3D元素数量

自测题

  1. 以下哪个属性用于开启3D空间,使子元素保持3D位置关系?

    • A. perspective
    • B. transform-style: preserve-3d
    • C. backface-visibility: hidden
    • D. transform: translate3d()

    答案:B

  2. 要实现元素沿X轴旋转90度,同时具有透视效果,正确的CSS是?

    /* A */
    .box {
      transform: rotateX(90deg);
    }
    
    /* B */
    .container {
      perspective: 600px;
    }
    .box {
      transform: rotateX(90deg);
    }
    
    /* C */
    .box {
      perspective: 600px;
      transform: rotate(90deg);
    }
    
    /* D */
    .container {
      transform-style: preserve-3d;
    }
    .box {
      transform: rotateX(90deg);
    }
    

    答案:B(需在父容器设置perspective提供透视环境)

  3. 3D变换中,translateZ(100px)translateZ(-100px)的视觉效果区别是?

    答案:translateZ(100px)使元素沿Z轴正向移动(靠近观察者,视觉变大);translateZ(-100px)沿Z轴负向移动(远离观察者,视觉变小)

  4. 实现卡片翻转效果时,为什么需要设置backface-visibility: hidden

    答案:防止卡片翻转过程中正面和背面同时可见(重叠显示),设置后旋转超过90度时背面自动隐藏,提升视觉效果

扩展阅读