探索 CSS 3D 属性:从基础到炫酷动画案例

发布于:2025-09-10 ⋅ 阅读:(22) ⋅ 点赞:(0)

CSS 3D 属性为页面带来了全新的视觉维度,让原本平面的元素能够在三维空间中展示和运动,极大地提升了用户体验和页面表现力。本文将从 CSS 3D 的核心概念和属性讲起,逐步深入,最后通过两个实用的案例动画,帮助你全面掌握 CSS 3D 技术的应用。

一、先搞懂 CSS 3D 的 3 个核心概念

在写代码前,必须先建立 “3D 空间” 的认知 ——CSS 3D 本质是在浏览器中模拟三维坐标系,所有元素都在这个坐标系中定位和变换。这三个概念是一切效果的基础:

1. 3D 坐标系:x/y/z 轴分别代表什么?

CSS 3D 采用 “右手坐标系”,记住这三个轴的方向,就能理解元素的移动和旋转逻辑:

  • x 轴:水平方向(左右),正方向向右,负方向向左;
  • y 轴:垂直方向(上下),正方向向下,负方向向上;
  • z 轴:纵深方向(前后),正方向指向屏幕外(靠近你),负方向指向屏幕内(远离你)。

2. perspective:给眼睛一个 “距离”,让 3D 有立体感

没有 perspective 的 3D 都是 “假 3D”—— 它模拟人眼到 “3D 舞台” 的距离,值越小,立体感越强(就像凑近看物体),值越大,立体感越弱(像远处看)。

注意:perspective 要加在父容器上,作用是给子元素创建 “3D 观察空间”,而不是直接加在子元素上。

3. transform-style: preserve-3d:让子元素 “继承” 3D 空间

默认情况下,CSS 会把 3D 变换后的子元素 “压平” 到父元素的平面上(transform-style: flat),这会导致子元素之间的 3D 层级消失。只有给父容器设置 transform-style: preserve-3d,才能让子元素在真正的 3D 空间中排列。

二、从基础到进阶:3 个实战案例

理论说完,直接上代码 —— 每个案例都包含完整 HTML/CSS,复制到文件就能运行,关键代码已标注注释。

案例 1:3D 旋转立方体(基础入门)

最经典的 3D 案例,用 6 个 div 组成立方体的 6 个面,通过 transform 定位到 3D 空间,再添加旋转动画。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D立方体旋转效果</title>
    <style>
        .cube-stage {
            width: 400px;
            height: 400px;
            margin: 80px auto;
            perspective: 1500px;
            /* 透视效果,增强立体感 */
        }

        .cube {
            width: 100%;
            height: 100%;
            position: relative;
            transform-style: preserve-3d;
            /* 开启3D空间 */
            animation: rotateCube 10s linear infinite;
            /* 自动旋转动画 */
        }

        /* 立方体的6个面 */
        .cube-face {
            width: 200px;
            height: 200px;
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -100px;
            margin-left: -100px;
            opacity: 0.8;
            border: 2px solid white;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 24px;
            color: white;
            font-weight: bold;
        }

        /* 前面:沿Z轴正向平移100px(立方体边长的一半) */
        .front {
            background-color: #4285f4;
            transform: translateZ(100px);
        }

        /* 后面:沿Z轴负向平移100px,再绕Y轴旋转180度 */
        .back {
            background-color: #ea4335;
            transform: translateZ(-100px) rotateY(180deg);
        }

        /* 左面:沿X轴负向平移100px,再绕Y轴旋转-90度 */
        .left {
            background-color: #fbbc05;
            transform: translateX(-100px) rotateY(-90deg);
        }

        /* 右面:沿X轴正向平移100px,再绕Y轴旋转90度 */
        .right {
            background-color: #34a853;
            transform: translateX(100px) rotateY(90deg);
        }

        /* 上面:沿Y轴负向平移100px,再绕X轴旋转90度 */
        .top {
            background-color: #9c27b0;
            transform: translateY(-100px) rotateX(90deg);
        }

        /* 下面:沿Y轴正向平移100px,再绕X轴旋转-90度 */
        .bottom {
            background-color: #00acc1;
            transform: translateY(100px) rotateX(-90deg);
        }

        /* 立方体旋转动画:绕X轴和Y轴同时旋转 */
        @keyframes rotateCube {
            0% {
                transform: rotateX(0deg) rotateY(0deg);
            }

            100% {
                transform: rotateX(360deg) rotateY(360deg);
            }
        }
    </style>
</head>

<body>
    <div class="cube-stage">
        <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>
</body>

</html>

关键思路
立方体的边长是 300px,所以每个面需要向对应方向移动 “边长的一半”(150px),才能刚好组成立方体;旋转动画同时绕 x 轴和 y 轴,让立方体的 6 个面都能展示出来。

案例 2:3D 翻牌效果(交互进阶)

在实际项目中,3D 翻牌常用于卡片详情、答题对错判断等场景。这个案例实现 “鼠标悬停时,卡片从正面翻到背面” 的效果。

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>CSS 3D 翻牌效果</title>
    <style>
        /* 1. 卡片容器:设置 3D 空间和尺寸 */
        .card-container {
            width: 400px;
            height: 600px;
            margin: 50px auto;
            perspective: 1200px;
            /* 稍大的距离,让翻牌更自然 */
            cursor: pointer;
        }

        /* 2. 卡片主体:承载正反面,设置 3D 保留和过渡 */
        .card {
            width: 100%;
            height: 100%;
            position: relative;
            transform-style: preserve-3d;
            /* 关键:添加过渡,让翻牌有动画感 */
            transition: transform 0.6s ease;
        }

        /* 3. 鼠标悬停时:卡片绕 y 轴旋转 180° */
        .card-container:hover .card {
            transform: rotateY(180deg);
        }

        /* 4. 卡片正反面:统一样式,隐藏背面(关键) */
        .card-front,
        .card-back {
            position: absolute;
            width: 100%;
            height: 100%;
            backface-visibility: hidden;
            /* 关键:隐藏被旋转到背面的元素(避免正面和背面重叠) */
            border-radius: 16px;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 30px;
            box-sizing: border-box;
        }

        /* 5. 正面样式 */
        .card-front {
            background: linear-gradient(135deg, #ff6b6b, #feca57);
            color: #fff;
        }

        /* 6. 背面样式:默认旋转 180°(初始状态背对用户) */
        .card-back {
            background: linear-gradient(135deg, #48dbfb, #1dd1a1);
            color: #fff;
            transform: rotateY(180deg);
            /* 关键:初始状态背面朝上(但被 backface-visibility 隐藏) */
        }

        /* 辅助样式:图片和文字 */
        .card-img {
            width: 200px;
            height: 200px;
            border-radius: 50%;
            margin-bottom: 30px;
            object-fit: cover;
        }

        .card-title {
            font-size: 32px;
            margin-bottom: 16px;
        }

        .card-desc {
            font-size: 18px;
            text-align: center;
            line-height: 1.6;
        }
    </style>
</head>

<body>
    <div class="card-container">
        <div class="card">
            <!-- 卡片正面 -->
            <div class="card-front">
                <img src="https://picsum.photos/200/200?random=1" alt="正面图片" class="card-img">
                <h2 class="card-title">前端进阶笔记</h2>
                <p class="card-desc">点击卡片,查看 CSS 3D 核心知识点</p>
            </div>
            <!-- 卡片背面 -->
            <div class="card-back">
                <h2 class="card-title">CSS 3D 核心属性</h2>
                <p class="card-desc">1. perspective:创建 3D 观察距离<br>2. transform-style: preserve-3d:保留 3D 层级<br>3.
                    backface-visibility: hidden:隐藏背面元素<br>4. transform: rotateY(180deg):绕 y 轴旋转</p>
            </div>
        </div>
    </div>
</body>

</html>

关键思路

  • backface-visibility: hidden 是核心:它让元素的 “背面” 在旋转时不可见,避免正面和背面重叠显示;
  • 背面初始状态用 rotateY(180deg) 旋转,这样默认显示正面;鼠标悬停时,卡片整体旋转 180°,背面就会转到正面。

案例 3:3D 照片墙(综合实战)

用多个图片元素组成 “立体照片墙”,鼠标拖动时照片墙跟随旋转,模拟真实空间的交互感。这个案例需要结合一点 JavaScript 处理鼠标事件。

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>CSS 3D 照片墙</title>
    <style>
        /* 1. 全局样式:消除默认边距,设置背景 */
        body {
            margin: 0;
            padding: 50px;
            background: #2c3e50;
            min-height: 100vh;
            box-sizing: border-box;
        }

        /* 2. 照片墙容器:3D 空间和居中 */
        .photo-wall {
            width: 800px;
            height: 500px;
            margin: 0 auto;
            position: relative;
            perspective: 1500px;
            /* 更大的距离,让照片墙更有空间感 */
            transform-style: preserve-3d;
        }

        /* 3. 照片样式:绝对定位,添加过渡 */
        .photo {
            position: absolute;
            width: 300px;
            height: 400px;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            /* 初始居中 */
            backface-visibility: hidden;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
            transition: transform 0.3s ease;
            /* 平滑过渡,跟随鼠标移动 */
            overflow: hidden;
        }

        /* 4. 照片图片:填充容器 */
        .photo img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            display: block;
        }
    </style>
</head>

<body>
    <div class="photo-wall" id="photoWall">
        <!-- 这里会用 JS 动态生成 6 张照片 -->
    </div>

    <script>
        // 1. 获取照片墙容器
        const photoWall = document.getElementById('photoWall');
        // 2. 照片数量和角度分布(6 张照片,均匀分布在 360° 圆周上)
        const photoCount = 6;
        const angleStep = 360 / photoCount; // 每张照片之间的角度差:60°
        const radius = 300; // 照片墙的“半径”(照片到中心的距离)

        // 3. 动态生成照片
        for (let i = 0; i < photoCount; i++) {
            const photo = document.createElement('div');
            photo.className = 'photo';
            // 给每张照片设置不同的旋转角度和位置(核心:利用 rotateY 和 translateZ)
            const angle = i * angleStep; // 当前照片的旋转角度
            photo.style.transform = `
        translate(-50%, -50%) 
        rotateY(${angle}deg)  /* 绕 y 轴旋转对应角度 */
        translateZ(${radius}px) /* 向 z 轴正方向移动半径距离,形成圆形 */
      `;
            // 添加图片(使用随机图片服务)
            const img = document.createElement('img');
            img.src = `https://picsum.photos/300/400?random=${i + 2}`;
            img.alt = `照片 ${i + 1}`;
            photo.appendChild(img);
            photoWall.appendChild(photo);
        }

        // 4. 鼠标拖动控制旋转(交互核心)
        let isDragging = false;
        let startX = 0;
        let currentRotateY = 0; // 当前照片墙的旋转角度

        // 鼠标按下:记录初始位置
        photoWall.addEventListener('mousedown', (e) => {
            isDragging = true;
            startX = e.clientX;
        });

        // 鼠标移动:计算旋转角度
        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            const moveX = e.clientX - startX;
            // 控制旋转速度(移动 1px 对应旋转 0.5°,可调整)
            currentRotateY += moveX * 0.5;
            startX = e.clientX;
            // 应用旋转到照片墙
            photoWall.style.transform = `rotateY(${currentRotateY}deg)`;
        });

        // 鼠标松开:结束拖动
        document.addEventListener('mouseup', () => {
            isDragging = false;
        });

        // 鼠标离开窗口:结束拖动(避免异常)
        document.addEventListener('mouseleave', () => {
            isDragging = false;
        });
    </script>
</body>

</html>

关键思路

  1. 照片排列:6 张照片按 60° 间隔绕 y 轴旋转,再用 translateZ 向外移动相同距离,形成一个 “圆柱形” 的照片墙;
  2. 鼠标交互:通过监听 mousedown/mousemove/mouseup 事件,计算鼠标水平移动距离,转化为照片墙的旋转角度,实现 “拖动旋转” 的交互。

三、CSS 3D 开发的 3 个避坑指南

  1. 不要忘记 transform-style: preserve-3d:如果子元素的 3D 效果不显示,先检查父容器是否加了这个属性(很多新手会漏掉);
  2. perspective 的作用对象是父容器:直接给子元素加 perspective 无效,必须加在父容器上,让子元素在父


网站公告

今日签到

点亮在社区的每一天
去签到