这个项目标题打眼一看就容易让人想起那种“算了还是让设计出图吧”的场景。但我用 CSS 实际做下来之后,反而有些上瘾:只要把几个核心参数吃透,很多之前必须丢给 Photoshop 才能出片的效果,在网页里直接敲几十行样式就能出,甚至还能跟着鼠标动、跟着滚动动、跟着用户输入实时变。这篇文章就从我这个长期折腾前端动效的人的角度,把“用 CSS 做 3D 文字”这件事从头到尾拆一遍,包含原理、可复现代码、参数背后的取舍,以及踩坑记录。无论你是刚入门前端的小白,还是已经写了好几年样式想找点新玩法的老手,这套实操内容应该都能直接抄作业。
1. 动手前的设计思路:同样是3D文字,为什么我不开PS
1.1 纯CSS方案到底解决了什么问题
很多人第一反应是,做个 3D 文字而已,用 PS 拉个图层样式,导出 PNG 不就行了?如果你的页面内容永远不变,当然可以。但只要是做前端的人,迟早会遇到下面这些情况:
- 标题文字需要根据后台配置动态变化,比如用户昵称、随机生成的活动文案,总不能每次变化都让设计导出新图。
- 需要文字随着鼠标或滚动产生透视反馈,静态图完全做不到。
- 团队想减少页面图片体积。一个 3D 文字的 PNG 动辄几十上百 KB,而一段 CSS 往往只有 1~2KB,尤其在做落地页时,移动端性能差异很明显。
- 想要在运行时给文字加动画、加滤镜、加过渡,图片方案全都锁死了。
所以“用 CSS 干翻 PS”这个口号,并不是说 CSS 能完成 PS 的所有炫技,而是在“界面中的标题文字特效”这个具体场景里,CSS 更轻量、更可控、更贴近 Web 的交互模型。它能做到很多人低估的东西,甚至能模拟出“伪图层样式叠加”的效果,而且代码量并不多。
1.2 两条实现路线:假3D与真3D
做 3D 文字特效,行业内基本分两大流派。理解这两条路线的差异,比直接背代码重要得多。
第一条是“假 3D”路线,核心靠 text-shadow 的多层叠加。每隔 1px 或 2px 叠一层阴影,层数多了以后,视觉上会产生一种“文字从纸面上凸起来”或“凹陷下去”的错觉。这种方案的优点是兼容性极好、代码结构简单,缺点是它本质上是 2D 的,无法响应透视角度变化,但胜在普适性极高,适合做按钮文字、标题的立体质感、活动页主视觉。
第二条是“真 3D”路线,核心靠 CSS 的 transform-style: preserve-3d 和 perspective。把文字拆成多个元素或使用多层伪类,在 Z 轴方向拉开距离,再给父容器一个透视角度,那么文字就会真正拥有深度,旋转容器时能看到文字的前后层次。这种方案适合做产品展示、名片翻转、3D 相册、引导页里的动态标题。
搞清楚自己要哪种效果,后面实现思路完全不一样。我在实际项目里的习惯是,纯展示型、稳定型页面优先用 text-shadow 方案;需要交互、需要动起来,再去上 preserve-3d。
1.3 这套实战需要什么基础
这篇实战的内容前端小白完全可以跟下来。要准备的不多:
- 一个编辑器,VSCode 之类的就行。
- 一个现代浏览器,Chrome 或 Edge 都没有问题。
- 基本的 HTML/CSS 结构感就可以,至少知道
<h1>、<style>标签是干什么的,如果会一点 flex 布局更好,不会也不影响,我会尽量写得细。
下面的内容是完全可以从零复制粘贴运行起来的。建议不要把代码扫一眼就关掉,自己动手改几个参数,比如层数、透视值、颜色,那种手感才会积累成你自己的经验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础中的基础:用text-shadow堆出立体感
2.1 为什么多层阴影会产生“厚度感”
text-shadow 的标准用法是“文字后面拖个模糊影子”,这很正常。但如果你去掉模糊半径,只保留偏移,再复制很多份,每一份都比上一份更暗一点,就会得到一个类似“文字的侧边被拉了厚度”的视觉结果。
原理并不复杂。光线如果从左上角照过来,文字朝右下方向的边缘会被照亮,反过来文字远离光线的左侧上侧就会落下一层层暗色投影。我们用 0 模糊的深色阴影一层一层向某个方向偏移,实际上是在模拟光线被文字遮挡后在侧边产生的厚度区域。层与层之间的色差越小,位移间隔越大,质感越接近硬边塑料;色差越大、位移间隔越小,质感越接近雕刻效果。
第一次看到效果时,很多人都会觉得这种“土办法”居然能有这么接近 PS 图层样式的效果。我当初也是这个感觉, PS 里加描边加斜面浮雕,导出图片,而 CSS 只需要在 text-shadow 上叠加几行数字。
2.2 新手向:最简单的凸起立体字怎么做
先把代码写出来,目标效果是:白字、从左上往下突出、有点类似糖果塑料质感。
html复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 3D文字 - text-shadow 立体字</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #0d1b2a;
font-family: 'Arial Black', 'Microsoft YaHei', sans-serif;
}
.stereo-title {
font-size: clamp(2.5rem, 8vw, 6rem);
font-weight: 900;
color: #ffffff;
letter-spacing: 0.08em;
text-shadow:
0 1px 0 #e0e0e0,
0 2px 0 #d0d0d0,
0 3px 0 #c0c0c0,
0 4px 0 #b0b0b0,
0 5px 0 #a0a0a0,
0 6px 0 #909090,
0 7px 12px rgba(0, 0, 0, 0.6);
}
</style>
</head>
<body>
<h1 class="stereo-title">3D Text</h1>
</body>
</html>
这个效果的核心点在于,前面 7 组阴影都没有模糊半径,只有 Y 轴偏移;最后一组加了模糊半径来投出柔和阴影。用手敲一遍这个 text-shadow 列表就会发现,每增加一层,就能明显看到侧面高度多了一截。字体的叠加权重越粗,效果越厚重;如果用的是系统默认细字体,层数再多也很难有肉感,所以这部分我强烈建议搭配 font-weight: 900 或 Black 字重。
2.3 原理之后是变化:凹刻、发光、故障风
立体字做法学会之后,稍微改两点就能延伸出好几种完全不同的感觉。
凹刻效果,就是把文字本身的颜色加深,阴影反过来变成亮色向下偏移或者向上偏移,模拟出光从上方照进凹槽。文字颜色本身偏深,阴影最上面那层用亮色,比如下面这样:
css复制.engrave-title {
color: #2c3e50;
text-shadow:
0 1px 0 #ffffff,
0 -1px 2px rgba(0, 0, 0, 0.4);
}
发光文字更适合做活动页标题。在颜色上用高饱和度的亮色,在阴影上多做几层带模糊的扩散。这里有一个我的实用参数:模糊半径从 4px 开始,逐层放大,同时每层的透明度递减。
css复制.glow-title {
color: #00e5ff;
text-shadow:
0 0 4px #00e5ff,
0 0 10px #00e5ff,
0 0 20px #0099cc,
0 0 40px #006699;
}
故障风相对复杂一点,通常把文字拆成三个不同颜色的副本,分别错位 2~3px,并限制部分显示。但用 text-shadow 可以快速模拟一个简化版:同一层文字上叠两个错位的不透明阴影,一个偏红向左边移动,一个偏青向右边移动,再给最外圈加一层细小的毛刺。
css复制.glitch-title {
color: #ffffff;
text-shadow:
-3px 0 0 rgba(255, 0, 60, 0.8),
3px 0 0 rgba(0, 255, 240, 0.8),
0 0 6px rgba(120, 120, 255, 0.4);
}
真实的故障风使用动画时,会每隔几帧切换一次阴影位置,形成信号干扰的感觉。如果只是静态场景,这种双色错位是性价比最高的入门款。
2.4 使用text-shadow时的兼容性和性能提醒
text-shadow 几乎所有现代浏览器都支持,移动端也没问题。但有三点值得注意:
第一,阴影层数不是越多越好,层级在 10 层以上虽然效果更厚,但是在低端安卓机上滚动或动画时可能会出现掉帧,尤其是多个标题同时存在时。保守做法是 6~8 层就够,靠加大字号和字体字重来弥补体积感。
第二,要区分阴影方向和光源方向。光源在左上角,投影在右下;光源在正上方,投影几乎垂直向下。整页最好统一光源,不然几个标题放在一起,一个往右下凸,一个往左下凹,会显得很奇怪。
第三,如果文字带了半透明背景图片,注意阴影会被盖住,这时候一般需要给容器单独设置 isolation: isolate,或者用伪元素把文字阴影做在文字层下面,避免图层顺序上的意外。
3. 真3D玩法:CSS transform 构建可旋转的文字场景
3.1 从假3D走向真3D需要理解的三件事
text-shadow 再怎么堆,拍扁了看还是一张平面图。如果你想让人物围绕一排字旋转、或者文字所在的面跟随鼠标做出立体倾斜,就得换成 perspective + transform。
CSS 3D 的核心其实很简单:
- 父容器开启透视,相当于给整个舞台设置了一个“眼睛离物体多近”的参数
perspective。 - 元素自身设置
transform-style: preserve-3d,告诉浏览器,子元素在 3D 空间中的位移、旋转需要被真实渲染,而不是拍平。 - 子元素用
translateZ()、rotateX()、rotateY()等属性在三维方向摆放。
举一个最容易理解的类比:你在桌前看一本书,书页展开成一个小角度,书页上的字离你眼睛的距离各不相同,所以有些字大些,有些字小些,透视就是控制“眼睛到书”的距离的参数。perspective 越小,视野越挤压,3D 效果越夸张,但角度太大会变形到看不清文字;perspective 越大,越接近日常观察视角,效果越柔和。
3.2 三步搭建可旋转的3D文字卡片
下面这个例子是做一个立体感极强的 3D 标题,它在鼠标移动时会倾斜角度,文字前后分层明显,非常适合放在落地页的英雄区。
html复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS 真3D文字 - 交互旋转</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
font-family: 'Arial Black', 'Microsoft YaHei', sans-serif;
overflow: hidden;
}
.scene {
width: 700px;
height: 300px;
perspective: 800px;
display: flex;
align-items: center;
justify-content: center;
}
.card {
position: relative;
transform-style: preserve-3d;
transform: rotateX(18deg) rotateY(18deg);
transition: transform 0.2s ease-out;
}
.card .front,
.card .back,
.card .bottom {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 90px;
white-space: nowrap;
user-select: none;
backface-visibility: hidden;
}
.card .front {
color: #fff;
text-shadow: 0 0 20px rgba(255, 200, 0, 0.3);
}
.card .back {
color: #19232e;
transform: translate(-50%, -50%) translateZ(-30px);
}
.card .bottom {
color: #f5b301;
transform: translate(-50%, -50%) translateZ(30px);
}
.scene:hover .card {
transform: rotateX(28deg) rotateY(28deg) scale(1.02);
}
</style>
</head>
<body>
<div class="scene">
<div class="card">
<div class="back">CSS 3D</div>
<div class="front">CSS 3D</div>
<div class="bottom">CSS 3D</div>
</div>
</div>
</body>
</html>
这个例子把同一句“CSS 3D”分三层,放在不同 Z 轴高度上:最远的背面是深色,最前的中间是金色,视觉上会自然呈现厚度。核心就在于 .card 开启了 preserve-3d,三个子元素虽然文字内容相同,但因为 Z 轴位置不同,旋转时会互相错开,从而产生堆叠的体积感。
要真正拥有交互响应,不能只用 hover,还要监听鼠标移动来动态更新旋转角。可以加一点 JavaScript,但目标是文章聚焦 CSS,就先不展开。不过我可以分享一个参数经验:旋转角度尽量不要超过 35 度,超过之后透视变形会严重,文字边缘会出现明显的拉丝感,视觉体验反而不好。
3.3 真3D里最容易搞不明白的坐标系
新手经常会遇到“为什么旋转方向和我想要的不一样“,本质是对坐标轴理解不到位。CSS 3D 的坐标系是这样的:X 轴水平向右,Y 轴垂直向下,Z 轴垂直于屏幕朝向观看者。所以:
rotateX(正角度),元素上方往后倒、下方往前翘,像低头。rotateY(正角度),元素左侧往后转、右侧向前突出,像人在侧头。translateZ(正值),元素靠近观看者,会显得更大。translateZ(负值),元素远离观看者,会显得更小且被遮挡。
我在做 3D 文字卡面时习惯把文字主层放在 Z 轴正方向 20~40px,把底层背景放在 Z 轴负方向 10~30px。这样无论场景怎么旋转,前景永远有脱离背景的浮空感。如果所有子元素都在同一 Z 轴平面上,即使开了 preserve-3d,旋转起来也不会有层次感,这是新手最容易忽略的一点。
3.4 真3D可以玩出的进阶效果
文字 + 3D + 动画的组合空间很大,我再列举两个常见但效果出彩的方向,适合活动页、个人主页、登录页的标题。
第一个方向是文字进入动画。开场时文字整体绕着 Y 轴从 90 度转到 0 度,配合透明度变化,会有种“从门缝里挤出来”的立体入场感。用 @keyframes 加 transform 控制即可,注意动画期间保留最终帧状态 animation-fill-mode: forwards,不然动画结束会弹回初始角度。
第二个方向是文字碎片化,这个更烧脑一些,做法是把文字切成多个 span,每一个 span 站在不同的 Z 轴上,再来一个分散动画。类似做法适合发布会主视觉,但是需要考虑 JS 配合因为 CSS 本身没法按笔画拆分汉字,得依赖 splitText 这类 JS 库把字分离。
我不建议新手一上来就追求碎片化,能先把三层结构玩熟练,再去扩展每个 span 的延迟时间,会有更踏实的掌控感。
4. 完整实战:做一个能直接放进项目里的3D动效标题
4.1 目标效果拆解
把前面的知识点揉到一起,接下来做一个比较完整的实战案例:一个名为“NEON DROP”的霓虹色 3D 标题,作为页面展示区的主视觉。它的预期表现是:
- 文字本身有 3D 厚度,用多层颜色叠加实现。
- 一层背景光晕包围文字,营造霓虹灯管效果。
- 鼠标移动到卡片上时,标题整体随视角旋转,最大旋转角度约 20 度。
- 鼠标离开后,动画平滑回弹到初始角度。
- 适配移动端,文字大小响应式变化。
这个场景非常适合个人主页顶部的品牌展示,或者一个 SaaS 产品 landing page 的 hero 区块。整体代码量很少,但视觉完成度非常高。
4.2 完整实现代码
html复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NEON DROP - 3D霓虹文字实战</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background:
radial-gradient(circle at 50% 40%, #141e30 0%, #0b0f1a 100%);
font-family: 'Arial Black', 'Microsoft YaHei', sans-serif;
overflow: hidden;
}
.stage {
perspective: 900px;
display: flex;
align-items: center;
justify-content: center;
width: 90vw;
max-width: 900px;
height: 50vh;
min-height: 300px;
}
.neon-card {
transform-style: preserve-3d;
transform: rotateX(10deg) rotateY(0deg);
transition: transform 0.4s cubic-bezier(0.23, 1, 0.32, 1);
will-change: transform;
}
.neon-title {
position: relative;
font-size: clamp(3rem, 10vw, 8rem);
color: #bdfff8;
letter-spacing: 0.1em;
text-shadow:
0 0 8px rgba(65, 255, 210, 0.8),
0 0 20px rgba(65, 255, 210, 0.5),
0 0 40px rgba(65, 255, 210, 0.4),
0 0 80px rgba(65, 255, 210, 0.2);
}
/* 三个厚度层:用伪元素把同样文字复制到不同深度 */
.neon-title::before,
.neon-title::after {
content: attr(data-text);
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
white-space: nowrap;
}
.neon-title::before {
color: #1b6e68;
transform: translateZ(-12px);
text-shadow: none;
z-index: -1;
}
.neon-title::after {
color: #09e2c0;
transform: translateZ(8px);
text-shadow: none;
}
.stage:hover .neon-card {
transform: rotateX(22deg) rotateY(18deg);
}
</style>
</head>
<body>
<div class="stage">
<div class="neon-card">
<h1 class="neon-title" data-text="NEON DROP">NEON DROP</h1>
</div>
</div>
</body>
</html>
这段代码有一个值得仔细理解的设计:厚度层并非额外写两个 HTML 标签,而是用 ::before 和 ::after 伪元素,通过 attr(data-text) 把主标题的文字内容重新读取出来。这样页面结构非常干净,标题区域只有一个 <h1>。伪元素分别放在 translateZ(8px) 和 translateZ(-12px) 的位置,中间的主文字虽然没有设置 Z 轴位移,但三个元素因为 Z 轴深度不同而天然分出了前后。主文字发着霓虹光,前景伪元素颜色较深呈现内侧阴影,背景伪元素颜色最深,看起来就像是灯管背后的一块支撑底座。
4.3 代码里的核心设计思路
有几个参数在把这段代码搬到自己的项目时一定要按情况调整:
第一个是 perspective: 900px,我试过 600px 到 1200px 的区间。900px 是比较稳妥的中庸值,立体感足够,边缘变形又轻微。如果是移动端小屏幕,可以降低到 500~700px,会让 3D 倾斜更明显,因为小屏上文字的绝对像素更大,透视感会增强。
第二个是伪元素 Z 轴距离值。背景层 -12px,前景层 8px,两者差距 20px。数字越大,文字厚度越夸张但可能会干扰阅读。标题字号越大、笔画越粗,越能承受更大的 Z 轴差值,字小的时候不要把差值拉太大,不然从侧面看会像一摞牌而不是刻字。
第三个是 hover 只改变了父容器 .neon-card 的旋转角度。把 transition 放在旋转元素上,不用给文字单独加动画,所以实现了非常顺滑的跟随。如果你希望鼠标移动过程中文字实时跟随,就得引入 JS,用监听 mousemove 事件动态设置 rotateX 和 rotateY。CSS 是没法实时感知鼠标位置的,这一点要认清边界。
4.4 怎么把它扩展成鼠标跟随效果
如果项目环境允许 JS,我强烈建议把 hover 改成鼠标跟随,体验会立刻上一个档次。我在这里给一个非常简短的 JavaScript 补充版本。
html复制<script>
const stage = document.querySelector('.stage');
const card = document.querySelector('.neon-card');
stage.addEventListener('mousemove', (e) => {
const rect = stage.getBoundingClientRect();
const px = (e.clientX - rect.left) / rect.width - 0.5;
const py = (e.clientY - rect.top) / rect.height - 0.5;
card.style.transform = `rotateX(${(-py * 22).toFixed(2)}deg) rotateY(${(px * 22).toFixed(2)}deg)`;
});
stage.addEventListener('mouseleave', () => {
card.style.transform = 'rotateX(10deg) rotateY(0deg)';
});
</script>
这个脚本把鼠标在容器内的相对位置换算成 -0.5 到 0.5 的系数,再乘以最大旋转角度。鼠标向右,Y 轴旋转为正;鼠标向下,X 轴旋转为正。离开时回弹到初始角度。整段脚本约 10 行,但是完成度会远超纯 CSS hover,我会建议凡是展示型页面,都尽量用这种方案。
5. 常见问题与排查技巧实录
5.1 文字看不出立体感 / 阴影堆了不生效
这个问题我见过很多次,基本逃不出三个原因。
第一个是字体太细。text-shadow 的阴影层是靠文字的本体笔画撑起来的,细体字每一条笔画只有一两像素宽,阴影在这么窄的空间里几乎表现不出厚度。要改成 700 或更重的字重,或者选用本身就比较粗的字体。
第二个是阴影颜色和背景颜色太接近。比如白色背景上堆的是浅灰色阴影,肉眼很难察觉。做立体感测试时,先用深色背景配浅色文字、高对比度阴影,确认参数有效之后,再调整回符合设计稿的颜色。
第三个是偏移方向和颜色方向搞反了。如果你要的是凸起,阴影方向底部颜色要深于顶部或侧面,如果影子反而比文字颜色还亮,视觉上会产生凹陷的错觉。
真 3D 方向看不出来,大概率是父容器忘了写 perspective,或子元素没有 transform-style: preserve-3d。没有这两个属性中的任何一个,浏览器就会把所有子元素拉平到同一个平面渲染,Z 轴上的位移全部失效。这是 CSS 3D 最常见的隐性 bug。
5.2 伪元素复制文字后位置对不上
很多人在模拟厚度层时用伪元素,但发现伪元素里的文字和主文字错位、溢出,或者没显示出来。核心原因通常是没有给伪元素设置相同的水平对齐规则。
解决办法是让伪元素继承主元素的排版属性。最笨但最好用的方法:给主元素设置 position: relative,给伪元素设置 content: attr(data-text),并写上 left: 0、top: 0、width: 100%、height: 100%、white-space: nowrap。这样伪元素会以主元素的左上角为基准,并且继承上下文的字体族、字号、字重。如果主标题里有空格或中文,white-space: nowrap 很重要,不然换行后伪元素位置就会漂移。
还有一个细节,伪元素默认无法继承 font-family 以外所有属性,必须显式设置 font-size 和 font-weight,或者直接让它们使用继承值。如果伪元素里没有设置字体样式,浏览器可能用默认 UI 字体渲染,文字形状都不一样,立体效果自然对不上。
5.3 页面模糊锯齿 / 字体渲染不均匀
真 3D 旋转状态下的文字边缘偶尔会出现锯齿或轻微模糊。这是因为浏览器在 3D 变换后为了性能会降低部分采样率。解决思路有三个:
第一是给文字元素增加 transform: translateZ(0) 或者 will-change: transform,强制浏览器把它提升为独立合成层,用 GPU 来渲染,会缓解边缘模糊的问题。但不要把所有文字都加这个属性,会无端增加内存占用。
第二是尽量不使用带过多衬线装饰的字体做 3D 旋转,字体笔画太细密会在透视时闪烁。建议使用无衬线粗体字。
第三是给文字的 backface-visibility: hidden。如果做的是卡片双面效果,关掉背面渲染可以大幅减少渲染负担。如果不需要前后翻转效果,开它绝对利大于弊。
5.4 移动端性能表现不佳
如果你在手机浏览器里看到文字旋转卡顿,需要先检查是不是页面里用了太多大尺寸的模糊效果。filter: blur() 和 text-shadow 的大范围模糊在移动端合成成本很高。建议的做法是:将大块模糊只在静态状态下展示,动画过程中暂时移除它,或者在动画完成后重新应用,用 JS 控制 class 更灵活。
对于 text-shadow 立体字本身,层数可以降到 5 层以下,用颜色跳跃更大的阴影来模拟厚度,牺牲平滑度换取帧率。我把这个“降层数但提高对比”的策略称为移动端 3D 文字的性价比方案,实际用下来视觉损失很小。
5.5 兼容性速查
有人问 3D 文字特效是不是只能用 Chrome,目前主流浏览器对 text-shadow、preserve-3d 的支持已经相当成熟,Edge、Firefox、Safari 都没有问题。不过老旧国产浏览器内核版本如果停留在 Chromium 70 以下,backdrop-filter 之类的新特性不一定支持,但基础 text-shadow 和 transform 是可以的。如果只做移动端 H5,基本可以放心使用。
6. 一些提高效率的开发习惯
在最后,我分享几个能让你长期吃 CSS 3D 文字红利的开发习惯。
在编辑器里提前存几套模板。把 text-shadow 立体字、发光字、preserve-3d 卡片、伪元素厚度字分别存成 HTML 片段,项目里要用了直接改文字和颜色,比每次都从零写快非常多。
把常用的参数抽象成 CSS 变量。比如字体的厚度层数,用 --depth 变量定义主阴影的偏移距离,旋转角度用 --rot-x 和 --rot-y 定义。在调试时直接改 CSS 顶层变量,会比到处找硬编码值有效率得多。
多去逛一些纯粹做 CSS 特效的站点,给自己建立“效果库”。看到好效果时,第一反应不要是“以后让设计照着做”,而是“这个效果用的什么思路”。时间长了,你会慢慢练出一种职业嗅觉:看到视觉特效,脑子里的第一反应不再是图片文件,而是 CSS 层叠顺序和渲染开销。
尝试把文字特效的代码写进你自己维护的组件库,这样不只是自己爽,团队其他人也能直接复用。使用 JS 框架时,把特效封装成组件,输入参数接标题文本、颜色、字体、厚度、旋转角度,输出一段完整的 CSS 变量控制的核心代码,同事来问一次怎么改,直接告诉他全套配置都有接口。这也是前端工作里非常加分的产出方式。
说实话, 3D 文字的上限不在于 CSS 语法,而在于你愿不愿意在调试台里反复改参数,直到脑子里能预测出某个数值变换后的视觉效果。练到这种手感,不管接下来碰到的是 CSS 还是未来更新的渲染引擎,你都有能力快速上手。
我做这个效果踩过最典型的坑,就是一开始想推高 translateZ 让厚度更夸张,结果把前后层差调得太大,旋转时文字侧面出现了强烈的拉伸变形。后来把层差值控制在 20px 内,视角旋转控制在 30 度内,视觉稳定度好了很多。也希望你在这个基础上继续改,找到最适合自己场景的那组数字。
