前端 · CSS

CSS box-shadow:8 种现成可抄的阴影 + 那些性能坑

不是讲 4 个参数怎么写——是给你 8 段直接能用的代码,每个旁边显示真实渲染效果,再讲一下移动端滚动掉帧的修复方法。看完直接复制走。

语法 30 秒回忆

box-shadow: [inset] X Y blur spread color;

8 种现成阴影

柔和

1. 柔和阴影(最常用)

box-shadow: 0 4px 12px rgba(0,0,0,.10);

卡片、弹窗的"默认值"。偏移小、模糊大、透明度低。看起来像浮在桌面上很轻一点点。

浮起

2. 浮起感(hover 状态常用)

box-shadow: 0 12px 28px -8px rgba(0,0,0,.20);

spread 取负值让阴影向中间收紧,看起来物体离地更高。配 transition 做 hover 动效。

硬边

3. 硬边阴影(粗野/像素风)

box-shadow: 4px 4px 0 rgba(0,0,0,.30);

模糊 = 0,硬边偏移。NeoBrutalism 风格基础。最近 Tailwind 项目里特别多。

内阴影

4. 凹陷感(按下/输入框)

box-shadow: inset 0 2px 4px rgba(0,0,0,.15);

按钮 active 态、输入框 focused 态。让用户视觉感受到"凹下去了"。

霓虹

5. 霓虹光效(暗色模式好看)

box-shadow: 0 0 24px 4px rgba(99,102,241,.6);

偏移全 0,纯模糊 + 扩散 + 品牌色。亮色背景下太张扬;暗色模式或 dashboard 场景下效果惊艳。

多层

6. 多层叠加(Material 风)

box-shadow: 0 1px 2px rgba(0,0,0,.07), 0 4px 8px rgba(0,0,0,.05), 0 12px 24px rgba(0,0,0,.03);

三层不同 blur 的阴影叠加,更接近真实世界的光线衰减。比单层柔和阴影"更高级"。

边框

7. 替代 border(focus ring)

box-shadow: 0 0 0 2px rgba(99,102,241,.5);

spread 做"伪边框"。关键好处:不占布局空间,不会让元素尺寸变化。focus / selected 状态用这个比加 border 流畅得多。

浮雕

8. 双向内阴影(凹陷浮雕)

box-shadow: inset 0 2px 4px rgba(0,0,0,.15), inset 0 -1px 2px rgba(255,255,255,.6);

上深下亮,模拟"凿进去"的视觉。复古 skeuomorphism 设计、3D 卡片返潮时常见。

box-shadow vs filter: drop-shadow

这是面试题里常考但实际开发也容易搞混的:

对比box-shadowfilter: drop-shadow
作用对象盒子边界(矩形 / border-radius)元素的不透明像素
透明 PNG / SVG沿矩形外框投影沿不透明形状投影
支持 inset
性能更快(合成层友好)稍慢(光栅化)
典型场景卡片、按钮、容器带透明区域的图标/插画

简单记:矩形 + 圆角 → box-shadow;不规则形状 → drop-shadow

移动端性能坑

大面积阴影 + 列表滚动 + 中低端机 = 掉帧。原因是 box-shadow 触发新的 GPU 合成层,列表项越多合成开销越大。

/* 错误:每个列表项都来个 multi-layer 多层阴影 */
.list-item {
  box-shadow:
    0 1px 2px rgba(0,0,0,.07),
    0 4px 8px rgba(0,0,0,.05),
    0 12px 24px rgba(0,0,0,.03);
}

/* 正确:列表项用简单阴影;hover/active 时才升级 */
.list-item {
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
  transition: box-shadow .2s;
}
.list-item:hover {
  box-shadow: 0 4px 12px rgba(0,0,0,.12);
}
⚠️

真实事故:电商商品列表卡顿。Devtools Performance 一看,30% 时间在 Composite Layers。原因是每个商品卡片有 3 层 box-shadow,长列表 200+ 个商品同时合成。改成单层 + 滚停时才升级,FPS 从 32 回到 58。

动效中过渡阴影的"正确"姿势

.card {
  /* 把阴影初始值写好,避免从 "none" 到 "0 4px 12px..." 的不流畅过渡 */
  box-shadow: 0 0 0 rgba(0,0,0,0);
  transition: box-shadow .25s ease, transform .25s ease;
}
.card:hover {
  box-shadow: 0 8px 24px rgba(0,0,0,.15);
  transform: translateY(-2px);
}

多个属性一起动用 transform: translateYtop 高效(不触发 layout)。

暗色模式下调整阴影

同一个阴影值在亮色和暗色下视觉效果差很多——暗色背景上轻阴影几乎看不见。两种解法:

/* 方案 A:暗色下加深阴影 + 加白色高光 */
.card { box-shadow: 0 4px 12px rgba(0,0,0,.10); }
@media (prefers-color-scheme: dark) {
  .card {
    box-shadow:
      0 4px 16px rgba(0,0,0,.50),
      0 0 0 1px rgba(255,255,255,.05);  /* 微高光定义边界 */
  }
}

/* 方案 B:暗色下用品牌色发光(适合 dashboard) */
@media (prefers-color-scheme: dark) {
  .card:hover {
    box-shadow: 0 0 24px rgba(99,102,241,.3);
  }
}
💡

不想算 X/Y/blur?CSS box-shadow 可视化工具拖滑块实时预览,直接复制 CSS。

常见疑问

border-radius 之外的阴影会被截掉吗?

不会。box-shadow 沿 border 外缘投射,会跟着 border-radius 走弧度,: overflow:hidden 不会裁剪外阴影(外阴影不在元素 box 内);裁剪内阴影也需要靠 overflow:hidden

阴影颜色用半透明黑还是带色调?

取决于设计语言。简洁/中性风用 rgba(0,0,0,0.X)。彩色设计系统(比如 Stripe)会用带轻微品牌色调的阴影:rgba(50,50,93,0.1)——视觉上更"奢华"。

CSS box-shadow 可视化

拖滑块调 X/Y/blur/spread,实时预览,一键复制 CSS

打开工具