效果:

实现思路:
-
在根节点定义尺寸与配色等CSS变量(w、gap、allW、c1...bg)。
-
创建容器结构:.container 包裹 .container-box,并将页面居中显示。
-
设置透视与3D:给 .container 设置 perspective;给 .container-box 开启 preserve-3d。
-
构建六个面:创建 .cube-side(front/back/right/left/top/bottom),每个面内添加一个 .cube-grid。
-
使用 box-shadow 生成 3×3 方格阵列,依据 w 与 gap 计算偏移量形成九宫格。
-
用 translateZ/rotateX/rotateY 将六个面定位到立方体的正确位置。
-
启用背面隐藏:backface-visibility: hidden,避免背面闪烁或穿透导致的视觉问题。
-
添加旋转动画:定义 @keyframes rotate,并在 .container-box 上应用 animation。
-
可通过调整变量改变魔方大小、间距与颜色主题,实现快速定制。
附代码:
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>3D魔方</title>
<style>
:root {
--w: 60px;
--gap: 10px;
--allW: calc(3 * var(--w) + 4 * var(--gap));
--c1: #FF0000;
--c2: green;
--c3: #fff;
--c4: #97d497;
--c5: #291a80;
--c6: rgb(255, 0, 212);
--bg: #0d0e0d;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
display: grid;
place-items: center;
background: var(--bg);
color: #fff;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Noto Sans", "Apple Color Emoji", "Segoe UI Emoji";
}
.container {
width: var(--allW);
height: var(--allW);
perspective: 900px;
}
.container-box {
position: relative;
width: var(--allW);
height: var(--allW);
transform-style: preserve-3d;
animation: rotate 10s infinite alternate;
}
.cube-side {
width: 100%;
height: 100%;
position: absolute;
background: var(--bg);
border-radius: 7px;
padding: var(--gap);
backface-visibility: hidden;
}
.cube-side .cube-grid {
width: var(--w);
height: var(--w);
border-radius: calc(var(--w) / 5);
color: var(--c);
background: currentColor;
}
.cube-grid {
box-shadow:
calc(var(--w) + var(--gap)) 0 0 currentColor,
calc(var(--w) * 2 + var(--gap) * 2) 0 currentColor,
0 calc(var(--w) + var(--gap)) currentColor,
calc(var(--w) + var(--gap)) calc(var(--w) + var(--gap)) currentColor,
calc(var(--w) * 2 + var(--gap) * 2) calc(var(--w) + var(--gap)) currentColor,
0 calc(var(--w) * 2 + var(--gap) * 2) currentColor,
calc(var(--w) + var(--gap)) calc(var(--w) * 2 + var(--gap) * 2) currentColor,
calc(var(--w) * 2 + var(--gap) * 2) calc(var(--w) * 2 + var(--gap) * 2) currentColor;
}
/* Faces positioning */
.cube-side.side-front { transform: translateZ(calc(var(--allW) / 2)); }
.cube-side.side-back { transform: rotateX(-180deg) translateZ(calc(var(--allW) / 2)); }
.cube-side.side-right { transform: rotateY(90deg) translateZ(calc(var(--allW) / 2)); }
.cube-side.side-left { transform: rotateY(-90deg) translateZ(calc(var(--allW) / 2)); }
.cube-side.side-top { transform: rotateX(90deg) translateZ(calc(var(--allW) / 2)); }
.cube-side.side-bottom { transform: rotateX(-90deg) translateZ(calc(var(--allW) / 2)); }
@keyframes rotate {
0% { transform: rotateZ(0deg) rotateX(0deg) rotateY(0deg); }
15% { transform: rotateZ(45deg) rotateX(45deg) rotateY(45deg); }
30% { transform: rotateZ(45deg) rotateX(90deg) rotateY(90deg); }
45% { transform: rotateZ(45deg) rotateX(135deg) rotateY(135deg); }
60% { transform: rotateZ(45deg) rotateX(90deg) rotateY(180deg); }
75% { transform: rotateZ(45deg) rotateX(45deg) rotateY(225deg); }
100% { transform: rotateZ(45deg) rotateX(0deg) rotateY(270deg); }
}
</style>
</head>
<body>
<div class="container">
<div class="container-box">
<div class="cube-side side-front">
<div class="cube-grid" style="--c: var(--c1)"></div>
</div>
<div class="cube-side side-back">
<div class="cube-grid" style="--c: var(--c2)"></div>
</div>
<div class="cube-side side-right">
<div class="cube-grid" style="--c: var(--c3)"></div>
</div>
<div class="cube-side side-left">
<div class="cube-grid" style="--c: var(--c4)"></div>
</div>
<div class="cube-side side-top">
<div class="cube-grid" style="--c: var(--c5)"></div>
</div>
<div class="cube-side side-bottom">
<div class="cube-grid" style="--c: var(--c6)"></div>
</div>
</div>
</div>
</body>
</html>