实现凹陷效果的关键是box-shadow叠加两条inset阴影:浅色亮边(如inset 0 1px 1px #fff)和深色暗边(如inset 0 -1px 1px rgba(0,0,0,0.15)),偏移量±1px、模糊值≤2px,颜色需匹配背景以保自然立体感。

box-shadow 实现凹陷效果的关键参数组合
凹陷感不是靠背景色或边框“画”出来的,而是用 box-shadow 的内阴影(inset)配合明暗对比模拟视觉深度。核心在于:必须同时有浅色亮边 + 深色暗边,且偏移量要小(通常 ±1px),模糊值不宜超过 2px,否则会发虚、失真。
常见错误是只加一条 inset 阴影,比如 box-shadow: inset 0 2px 4px rgba(0,0,0,0.2) —— 这只会压出一个“脏边”,没有立体感。
- 正确做法是叠加两条
inset阴影:一条浅色向上/向左提亮边缘,一条深色向下/向右压暗边缘 - 例如:
box-shadow: inset 0 1px 1px #fff, inset 0 -1px 1px rgba(0,0,0,0.15) - 注意颜色选择:亮边用接近背景的浅色(甚至纯白),暗边用比内容区略深的灰,避免过重导致像“裂开”
- 如果父容器有背景渐变或图片,亮边建议改用
rgba(255,255,255,0.3)而非纯白,否则会突兀
伪元素 ::before/::after 能否替代 box-shadow?
能,但没必要。有人用绝对定位的伪元素盖一层半透明白色+一层半透黑来模拟凹陷,逻辑上可行,但引入了额外 DOM 层级、z-index 管理和定位计算,响应式下容易错位。
更实际的问题是:伪元素方案在缩放(transform: scale())或高 DPI 屏幕下,边缘容易出现亚像素渲染模糊,而 box-shadow 是浏览器原生合成,抗锯齿稳定。
立即学习“前端免费学习笔记(深入)”;
- 仅当需要动态控制“凹陷方向”(比如点击时从凹变凸)且 CSS 变量无法满足时,才考虑伪元素 +
transition - 绝大多数静态嵌块场景,
box-shadow更轻量、更可靠 - 别忘了加
border: none或统一border样式——有默认边框时,阴影会被遮挡或打架
移动端 Safari 下凹陷效果发虚或消失?
这是 WebKit 的已知渲染差异:iOS 15+ 对小尺寸 inset 阴影做了优化裁剪,模糊值 ≤1px 且偏移为 0 时可能直接不绘制。不是 bug,是性能策略。
解决方式很具体:把原本的 inset 0 1px 0 #ccc 改成 inset 0 1px 0.5px #ccc,哪怕只加 0.5px 模糊,就能强制触发渲染。
- 不要用
0.1px或0.01px—— Safari 会四舍五入归零 - 安卓 Chrome 和桌面端无此问题,所以这个修复只建议加在媒体查询里:
@supports (-webkit-appearance:none) { ... } - 如果嵌块本身有圆角(
border-radius),确保box-shadow的模糊值 ≤ 圆角值的一半,否则阴影会“溢出”到圆角外,破坏凹陷感
凹陷嵌块与 focus-visible 边框冲突怎么办?
当嵌块可聚焦(比如 button 或带 tabindex 的 div),系统默认的焦点环会盖住凹陷阴影,视觉上变成“先凹再凸”,体验割裂。
不能直接 outline: none —— 这违反可访问性。正确解法是重绘焦点样式,复用同一套凹陷逻辑,但反向强化:
- 用
:focus-visible单独定义焦点状态 - 把原凹陷阴影替换成更粗的亮边 + 暗边,例如:
box-shadow: inset 0 2px 2px #fff, inset 0 -2px 2px rgba(0,0,0,0.2) - 或者加一层外部高对比度轮廓:
outline: 2px solid #0066cc; outline-offset: 2px;,位置刚好卡在凹陷边缘之外 - 切记测试键盘 Tab 导航 —— 很多开发者只看鼠标点击效果,忽略了焦点路径是否清晰










