neumorphism 的核心是用 css 变量解耦光方向、色系与深度,而非硬编码 box-shadow;通过 --bg 动态计算 --neu-light/--neu-dark 色值,用 --neu-depth 统一控制浮雕强度,并联动 border-radius、inset 阴影等实现响应式立体效果。

Neumorphism 的核心不是堆叠多个 box-shadow,而是用 CSS 变量把「光的方向、色系关系、深度层级」解耦出来——否则改一个按钮颜色就得手动算三组阴影值,一换主题全崩。
为什么直接写死 box-shadow 值会失控
常见错误是复制粘贴类似这样的代码:box-shadow: 8px 8px 16px #d1d9e6, -8px -8px 16px #fff。问题在于:
- 背景色一变,
#d1d9e6和#fff就不再匹配,高光发灰或暗影消失 - 所有元素(按钮、卡片、输入框)必须各自维护一套阴影值,无法统一调控“凸起强度”
- 深色模式下,
#fff高光会过曝,但没人会为每个组件再写一遍媒体查询
--neu-light 和 --neu-dark 必须基于背景动态计算
Neumorphism 的立体感来自「同色系的明暗双阴影」,所以两个变量不能是固定色值,而应是相对于 --bg 的偏移:
body {
--bg: #e0e5ec;
--neu-light: hsl(calc(hue(var(--bg)) - 5), calc(saturation(var(--bg)) * 0.4), calc(lightness(var(--bg)) + 8%));
--neu-dark: hsl(calc(hue(var(--bg)) + 8), calc(saturation(var(--bg)) * 0.6), calc(lightness(var(--bg)) - 12%));
}
这样换背景色时,阴影自动适配;深色模式只需改 --bg,其余全链式更新。
注意:Chrome 支持 hsl() 中的 calc,但 Safari 旧版不支持嵌套 calc,稳妥做法是用 JS 注入变量,或预编译成 CSS 自定义属性 fallback。
用 --neu-depth 控制所有组件的“浮雕强度”
不同组件需要不同深度感:卡片要轻微凸起,按钮需明显可按压,而分隔线几乎不可见。统一用一个变量驱动:
-
--neu-depth: 4px→ 卡片、容器类元素 -
--neu-depth: 6px→ 按钮默认态 -
--neu-depth: 2px→ 输入框边框模拟
对应 CSS 写法:
.card {
box-shadow:
var(--neu-depth) var(--neu-depth) calc(var(--neu-depth) * 2) var(--neu-light),
calc(-1 * var(--neu-depth)) calc(-1 * var(--neu-depth)) calc(var(--neu-depth) * 2) var(--neu-dark);
}
这样全局调大 --neu-depth,所有组件立体感同步增强,无需逐个修改像素值。
圆角、内阴影、伪 3D 环都需要变量联动
真实项目里,border-radius 和阴影模糊度必须协同变化,否则边缘生硬:
-
--neu-radius: 12px→ 同时用于border-radius和box-shadow模糊半径 - 内阴影(如按下态)用
inset var(--neu-depth),而非固定inset 2px - 环形控件(如音量旋钮)需额外变量
--neu-ring-gap: 4px控制内外环间距,避免硬编码
最易被忽略的是:当 --neu-depth 设为 0(比如禁用态),必须显式重置 box-shadow: none,否则 calc 计算出 0px 0px 0px 仍会触发渲染层,影响性能。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











