HTML表格单元格(<td>或<th>)无法直接使用box-shadow实现内阴影,因其受table-layout约束;需通过伪元素::before(配合position: relative、inset box-shadow和z-index: -1)或background渐变模拟,inset关键字和负z-index缺一不可。

cell内阴影不是box-shadow能直接生效的场景
HTML表格单元格(<td>或<th>)默认是table布局,box-shadow在多数浏览器里对<td>不起作用——不是bug,是规范行为。这是因为<td>的渲染盒模型受table-layout约束,阴影被“裁掉”或根本不绘制。真正起效的方式是绕过单元格本身,改用内部元素承载阴影。
用伪元素::before在<td>里模拟内阴影
核心思路:给<td>设position: relative,再用::before绝对定位覆盖其内容区域,通过box-shadow和background叠加制造“内凹”错觉。这不是真正的内阴影,但视觉效果最接近且兼容性好(Chrome/Firefox/Safari/Edge均支持)。
实操要点:
- 必须给
<td>加position: relative,否则::before无法相对单元格定位 -
::before需设content: ""、position: absolute,并用inset: 0铺满整个单元格 - 阴影用
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1),inset关键词不可省略 - 为避免遮挡文字,
::before的z-index要设为负值(如-1),确保文字层在上
td {
position: relative;
padding: 8px;
}
td::before {
content: "";
position: absolute;
inset: 0;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
z-index: -1;
}
用background渐变+透明度模拟内阴影更轻量
如果只需顶部/底部轻微“压感”,不用真实阴影,background线性渐变配合透明色块更高效,无伪元素开销,也规避了z-index层叠问题。
立即学习“前端免费学习笔记(深入)”;
适用场景:
- 仅需单边阴影(如顶部暗边模拟凹陷)
- 需要极致性能(大量单元格时)
- IE11需支持(伪元素方案在IE中
inset阴影支持不稳定)
示例(顶部内阴影):
td {
background: linear-gradient(to bottom, rgba(0,0,0,0.05) 1px, transparent 1px),
white;
background-size: 100% 100%;
background-origin: padding-box;
}
注意:background-origin: padding-box确保渐变从内边距开始,不覆盖border;rgba(0,0,0,0.05)控制阴影浓度,数值越大越重。
为什么不用outline或border代替
有人尝试用outline偏移或双border制造阴影感,但会破坏表格结构:
-
outline不占布局空间,但无法实现“内”效果,且outline-offset正负值在<td>上行为不一致 - 多层
border(如border: 1px solid #eee; border-bottom: 2px solid #ccc)看似有层次,实则只是粗细差异,缺乏光影过渡,观感生硬 - 两者都无法响应鼠标hover或焦点状态下的动态阴影变化,扩展性差
真正需要交互反馈(比如hover时加深内阴影),还是得回到::before + inset box-shadow路径,并在:hover里调整box-shadow参数。
表格单元格的“内阴影”本质是视觉欺骗,没有标准API,关键在于选对载体(伪元素 or 背景)和锚点(position: relative or background-origin)。最容易漏掉的是inset关键字和z-index: -1,缺一就会看到阴影盖住文字或干脆不显示。



















