写CSS阴影这件事,很多人都有过同一种疲惫:给按钮加一层box-shadow,给卡片再加一层,给弹窗还得再来一层。每个元素的阴影都是独立的装饰,彼此之间没有任何物理关系。页面里明明有十几个元素,却像是各自活在平行宇宙里,光从哪来、照到谁身上,全靠开发者手动脑补。
Ambient CSS想解决的就是这个问题。它是一个用CSS实现基于物理的照明系统的框架,最大的特点是:只要定义光源,所有阴影、高光、表面渐变都会自动生成。不是给每个元素单独调参数,而是先建立一个共享的照明环境,让所有子元素从这个环境里推导出自己的明暗表现。
![]()
光变了,整个容器跟着变
传统做法里,改一个阴影意味着找到那个元素、改它的box-shadow值。如果页面里有多个元素共享同一套光照逻辑,就得改很多次。Ambient CSS把这件事反过来了:在父元素上设置光的方向和强度,容器里所有子元素统一更新。
它的引擎把UI表面建模成一种物理材质,由两个光源系统驱动——主光(key light)和补光(fill light)。每个元素读取共享的CSS自定义属性,然后生成五层复合阴影:
- 投影:根据物理高度缩放的方向性阴影和半影
- 圆角高光:朝向光源一侧的镜面内边缘高光
- 圆角阴影:另一侧边缘的柔和内阴影
- 倒角高光:光线击中的切面上宽幅的倒角内发光
- 倒角阴影:阴影边缘处的暗色倒角
照明行为经过物理计算,参照模型是在Blender里搭建的光线追踪3D场景,用来校准CSS渲染出来的效果。
五个维度拼出一个表面
每个元素由五组核心材质特性组合而成,分别控制不同的视觉维度:
- 结构:让元素参与照明计算
- 表面:背景照明渐变,分平面、凹面、凸面
- 边缘:倒角和圆角切割,分倒角、圆角、凹槽
- 材质:镜面反射和半透明,分哑光、光亮、玻璃
- 深度:投影高度,从0到3级
这五个维度可以自由组合。一个按钮可以是凸面加圆角加光亮材质加1级高度,一个面板可以是平面加倒角加哑光加0级高度。组合方式决定了它在当前光照环境下看起来是什么样。
表面渐变这里有个细节值得注意:它不是固定颜色,而是场景光照下的材质表现。所以一个.amb-surface类就能覆盖所有色相和明暗变化,不需要为每种颜色单独写一套渐变。
两种接入方式,纯CSS或React
如果只想用纯CSS,三步就能跑起来。先执行npm install @ambientcss/css安装包,再把样式表链接进HTML,最后在父元素上挂一个光照环境类名,比如.amb-light-tl表示光从左上角来。子元素加上对应的类名组合,阴影和高光就自动出现了。
React项目走组件路线。安装组件包和CSS包之后,用AmbientProvider包住整个应用,通过theme属性传入光源坐标、主光强度、补光强度。里面的AmbientButton、AmbientKnob、AmbientPanel会自动继承这套光照环境。
组件以预设形式提供,每个预设是运动学、数值、ARIA管理机制和绘制部件的组合。换预设重新渲染,机制会如实反映绘制结果。这意味着交互逻辑和视觉表现是分开的,换一套外观不需要重写行为。
光照方向有八个预设,也能自己调
光照方向提供了八个预设类名,挂在父元素上即可,设置会反映到所有子元素:.amb-light-tl、.amb-light-tr、.amb-light-bl、.amb-light-br、.amb-light-top、.amb-light-bottom、.amb-light-left、.amb-light-right。
如果想要更细致的控制,可以用自定义CSS变量,比如水平方向、垂直方向、主光强度、补光强度、光的色相和饱和度等,都可以单独设置。
表面渐变同样可以通过父元素上的类名来设置,比如.amb-surface、.amb-surface-concave、.amb-surface-concave-h、.amb-surface-convex。还可以用变量控制完全照明下的颜色和反射率等。
Ambient CSS为用CSS实现基于物理的照明系统提供了一套完整方案,纯CSS和React组件两种方式都能用。感兴趣的话可以去官网看演示。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.