text-shadow 的工作原理
text-shadow 在文字后面绘制一份经过移动和模糊的文字副本。你需要提供水平偏移、垂直偏移、可选的模糊值和颜色。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Text shadow</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 36px; font-weight: 700; color: #111827; }
p { margin: 12px 0; }
.hard { text-shadow: 3px 3px 0 #f59e0b; }
.soft { text-shadow: 2px 2px 6px rgb(0 0 0 / 35%); }
</style>
</head>
<body>
<p class="hard">Hard shadow</p>
<p class="soft">Soft shadow</p>
</body>
</html>
3px 3px 0 #f59e0b 表示向右 3px(物理方向,在任何书写方向下都一样)、向下 3px、不模糊、琥珀色。第二个阴影模糊 6px,使用半透明的黑色,这是营造细微立体感的常用配方。
语法
text-shadow: <offset-x> <offset-y> <blur-radius>? <color>?;
| 值 | 是否必填 | 含义 |
|---|
| offset-x | 是 | 正值把阴影向右移,负值向左移 |
| offset-y | 是 | 正值把阴影向下移,负值向上移 |
| blur-radius | 否(默认为 0) | 边缘的柔和程度;负值无效 |
| color | 否(默认为文字颜色) | 可以写在最前面或最后面 |
text-shadow: none 可以去掉继承来的阴影。修改下面的值,看看每个值的效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Text shadow tester</title>
<style>
body { font-family: system-ui, sans-serif; color: #111827; }
#sample { font-size: 44px; font-weight: 800; margin: 16px 0; }
</style>
</head>
<body>
<label>text-shadow: <input id="val" value="4px 4px 8px #2563eb" size="28"></label>
<p id="sample">Shadow</p>
<p><code id="out"></code></p>
<script>
const sample = document.getElementById('sample');
const input = document.getElementById('val');
const show = () => {
sample.style.textShadow = input.value;
document.getElementById('out').textContent =
'computed: ' + getComputedStyle(sample).textShadow;
};
input.addEventListener('input', show);
show();
</script>
</body>
</html>
试试 -4px -4px 0 #16a34a、0 0 10px red,以及用逗号分隔的两个阴影。
多重阴影:发光、描边与 3D
用逗号可以叠加多个阴影;第一个绘制在最上面。这一条规则就能做出三种效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Stacked shadows</title>
<style>
body { font-family: system-ui, sans-serif; font-size: 40px; font-weight: 800; margin: 0; }
div { padding: 12px 16px; }
.neon {
background: #111827; color: #eff6ff;
text-shadow: 0 0 4px #93c5fd, 0 0 12px #3b82f6, 0 0 24px #2563eb;
}
.outline {
color: #ffffff;
text-shadow: -2px -2px 0 #111827, 2px -2px 0 #111827,
-2px 2px 0 #111827, 2px 2px 0 #111827;
}
.deep {
color: #f59e0b;
text-shadow: 1px 1px 0 #b45309, 2px 2px 0 #b45309,
3px 3px 0 #b45309, 4px 4px 0 #92400e;
}
</style>
</head>
<body>
<div class="neon">Neon glow</div>
<div class="outline">Outlined</div>
<div class="deep">3D text</div>
</body>
</html>
- 发光: 偏移为零,模糊逐渐增大,放在深色背景上。
- 描边: 四个没有模糊的阴影,每条对角线方向一个。它适合细的描边;如果想要更粗且均匀的描边,可以改用
-webkit-text-stroke: 2px #111827 在字母边缘绘制轮廓线(虽然带有前缀,但所有当前浏览器都支持)。
- 3D: 一串没有模糊的阴影,每个比前一个多偏移 1px,让字母看起来像是挤压出来的立体字。
让文字在复杂背景上保持可读
照片或图案上的白色文字,在背景较亮的地方会丢失边缘。一个柔和的深色阴影可以把边缘找回来,而且不会出现可见的方框:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Readable on a pattern</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; }
.hero {
padding: 32px 16px;
background: repeating-linear-gradient(45deg, #fde68a 0 20px, #ffffff 20px 40px);
font-size: 32px; font-weight: 800; color: #ffffff;
}
.with { text-shadow: 0 1px 3px rgb(0 0 0 / 70%), 0 0 12px rgb(0 0 0 / 40%); }
</style>
</head>
<body>
<div class="hero">Without a shadow</div>
<div class="hero with">With a shadow</div>
</body>
</html>
阴影有帮助,但并不能保证对比度。对于叠在图片上的长段文字,还要在文字后面加一层纯色或渐变遮罩。
text-shadow 与 box-shadow 的区别
| text-shadow | box-shadow |
|---|
| 跟随的形状 | 字母的形状 | 元素的盒子(及其圆角) |
| 扩展值 | 没有 | 有 |
inset | 没有 | 有 |
| 多个阴影,用逗号分隔 | 支持 | 支持 |
卡片和按钮上的阴影,请看 box-shadow。
常见错误
- 在正文上使用又重又深的阴影。 它们会让字母的形状变模糊。阴影只用在标题和简短的标签上。
- 忘了写第二个偏移量。
text-shadow: 2px #000 是无效的;两个偏移量都必须写。
- 模糊值为负数。 它是无效的,整条声明都会被丢弃。
- 以为阴影会占据空间。 它只是绘制出来的;很大的阴影可能会盖住下一行,或者被
overflow: hidden 裁掉。
- 在浅色背景上做发光效果。 白底上的浅色光晕是看不见的。发光效果需要深色背景。