- UI组件
- 前端
- 设计系统
【免费下载链接】material-web
Material Design Web Components
Elevation(高度)是 Material Design 中两个表面沿 z 轴方向的相对距离,Material Web Components 通过<md-elevation>自定义元素与--md-elevation-levelCSS 自定义属性,把 M3 的六档阴影体系(0~+5)完整落地到 Web 平台。读完本篇,你将掌握如何用一行标记为任意容器自动铺满的投影、通过 transition 属性在悬停/按压等交互状态间平滑切换阴影、如何用颜色 token 定制阴影色,并理解底层双阴影合成(key + ambient shadow)的实现原理。
Elevation 是什么
根据 M3 规范 的定义,Elevation 是两个表面沿 z 轴(垂直于屏幕的方向)的相对距离。Material 的阴影系统被刻意限制为只有少数几个档位,这一"创意约束"迫使你在设计 UI 的阴影叙事(elevation story)时做出深思熟虑的取舍,而不是随意堆砌阴影。
Material 使用六档高度等级,每档对应一个 dp(密度无关像素)数值,命名反映了元素相对 UI 表面的距离:0、+1、+2、+3、+4、+5。其中元素的静止(resting)状态可以使用 0 到 +3 级,而+4 和 +5 级专门保留给用户交互状态,例如 hover(悬停)和 dragged(拖拽)。这意味着你应当把最高的两级高度当作"交互反馈"手段,而不是让普通静态卡片常年停留在高位。
在 Material Web Components 中,这一套体系由一个轻量的自定义元素承载:
// elevation/elevation.ts @customElement('md-elevation') export class MdElevation extends Elevation { static override styles: CSSResultOrNative[] = [styles]; }元素内部实现非常精简,internal/elevation.ts 只做两件事:在connectedCallback里设置aria-hidden="true"(避免 VoiceOver 把它识别为与内容并列的"分组"),并渲染出一个<span class="shadow">作为阴影承载节点。也就是说,<md-elevation>本身没有任何可见内容,纯粹是一层可感知的投影层。
基础用法:为任意表面添加高度
Elevation 可以通过--md-elevation-levelCSS 自定义属性在 0 到 5 之间取值。投影会自动填满最近的position: relative元素的尺寸与形状(圆角会被继承)。
<style> .surface { position: relative; border-radius: 16px; height: 64px; width: 64px; --md-elevation-level: 3; } </style> <div class="surface"> <md-elevation></md-elevation> <!-- Content --> </div>使用上有三个关键点:
- 宿主必须有定位上下文:阴影节点通过
position: absolute; inset: 0铺满,而它的定位基准是最近的position: relative祖先,因此承载表面必须设置position: relative(源码见 internal/_elevation.scss 中的:host, .shadow, .shadow::before, .shadow::after样式块)。 - 圆角自动继承:阴影使用
border-radius: inherit,所以只要给宿主设置圆角,阴影就会跟随宿主形状;每档阴影的具体圆角是否叠加由 Material 规范决定,本组件实现中直接继承宿主的圆角值。 <md-elevation>可以出现在内容任意位置:组件使用display: flex; pointer-events: none,不会拦截鼠标事件,也不会影响内容的可点击性。
从源码的阴影公式(internal/_elevation.scss)可以看到,阴影是两层 box-shadow 合成的:
.shadow::before为key shadow(主投影),opacity: 0.3,负责给出物体的"着地感";.shadow::after为ambient shadow(环境投影),opacity: 0.15,负责大范围的环境光晕。
每档等级对应的 key shadow 目标值(源码注释中给出)为:
| Level | Key box-shadow | Ambient box-shadow |
|---|---|---|
| 0 | 0px 0px 0px 0px | 0px 0px 0px 0px |
| 1 | 0px 1px 2px 0px | 0px 1px 3px 1px |
| 2 | 0px 1px 2px 0px | 0px 2px 6px 2px |
| 3 | 0px 1px 3px 0px | 0px 4px 8px 3px |
| 4 | 0px 2px 3px 0px | 0px 6px 10px 4px |
| 5 | 0px 4px 4px 0px | 0px 8px 12px 6px |
实现上,Sass 用一组clamp(0, var(--_level) - N, M)的分段函数把连续的--_level映射到离散的 y / blur / spread 值,再乘以1px得到最终 box-shadow。这种"用 CSS 计算把 0~5 离散值换算成阴影参数"的手法,正是组件支持动画的关键——因为阴影参数是直接由 CSS 变量实时推导的,改变--md-elevation-level时无需重建任何样式。
动画:在高度等级间平滑过渡
在表面切换高度等级时,可以给宿主添加transition-duration与transition-easing-function(或transition-timing-function)属性,阴影就会平滑过渡。组件内部已经把transition-duration、transition-property、transition-timing-function全部设置为inherit,因此宿主上的过渡设置会被阴影层完整继承。
<style> .surface { /* ... */ transition-duration: 250ms; transition-timing-function: ease-in-out; --md-elevation-level: 3; } .surface:active { --md-elevation-level: 0; } </style> <div class="surface"> <md-elevation></md-elevation> <!-- Content --> </div>要点说明:
- 组件默认在
:host与.shadow::before/::after上设置transition-property: box-shadow, opacity,确保只有阴影相关的属性参与过渡,避免不必要的重排; - 上面示例利用
:active状态实现"按压时降至 0 级"的物理反馈,这正符合 M3 中"静止状态 0~+3、交互状态 +4~+5"的用法延伸——反过来,hover 时升到 +4/+5 也同样是推荐的交互模式; - 过渡时长(如 250ms)与缓动函数(如 ease-in-out)完全由你在宿主上控制,组件不做硬编码。
仓库的演示代码也验证了这一模式,elevation/demo/stories.ts 中每个 demo 盒子都设置了transition-duration: 250ms; transition-timing-function: ease-in-out;,而 elevation/demo/demo.ts 通过levelknob 让你可以在 0~5 之间实时拖动切换(渲染时用Math.min(Math.max(level, 0), 5)把输入夹在合法区间内),直观观察阴影过渡效果。
无障碍
Elevation 是一个纯视觉组件,不承载任何语义与交互信息,因此没有无障碍方面的顾虑。组件实现中唯一与无障碍相关的处理,是在挂载时为自身设置aria-hidden="true",避免屏幕阅读器把阴影层误读为内容分组(源码注释见 internal/elevation.ts)。在使用时,你无需为投影层提供任何 ARIA 属性或替代文本。
Theming:用 Material 主题定制阴影
Elevation 支持 Material theming,可以从颜色维度进行定制。它遵循与其它组件一致的 token 体系(Sass 侧见 elevation/_elevation.scss 的@forward './internal/elevation' show theme,样式侧见 internal/_elevation.scss 的theme($tokens)mixin),支持且仅支持两个 token:
| Token | 默认值 |
|---|---|
--md-elevation-level | 0 |
--md-elevation-shadow-color | --md-sys-color-shadow |
这两个 token 的定义来自 tokens/_md-comp-elevation.scss:
level取自md-sys-elevation.level0,默认即为 0,对应"无投影";shadow-color取自md-sys-color.shadow,也就是系统色板中的 shadow 色(tokens/_md-sys-color.scss 中注册的'shadow'token),默认通常接近黑色。
值得留意的是,tokens/_md-sys-elevation.scss 中有一处针对 Web 平台的特殊处理:注释明确指出"Web 端的高度等级应使用等级数字而非 dp 值"(level0~level5 被映射为整数 0~5),这正是你在页面上看到--md-elevation-level: 3而不是12dp之类写法(level3 对应的 dp 值)的原因。
主题化示例:自定义阴影颜色
<style> .surface { position: relative; border-radius: 16px; height: 64px; width: 64px; } :root { --md-elevation-level: 5; --md-sys-color-shadow: #006A6A; } </style> <div class="surface"> <md-elevation></md-elevation> <!-- Content --> </div>这个例子做了两件事:
- 通过
:root把--md-elevation-level提升到 5(所有表面默认获得最高级投影); - 把系统 token
--md-sys-color-shadow覆盖为青绿色#006A6A,让阴影呈现品牌色。
因为组件样式中的阴影颜色读取的是var(--_shadow-color),而_shadow-color又回落到var(--md-elevation-shadow-color, ...),最终落到--md-sys-color-shadow,所以在:root覆盖任何一个环节都能全局生效——这也解释了为何示例中只需要改--md-sys-color-shadow一个变量。若只想改变单个表面的阴影色,把--md-elevation-shadow-color直接写在对应类上即可。
若使用 Sass 构建,还可以通过组件暴露的theme($tokens)mixin 以编程方式注入 token:
// 需要引入 tokens 模块与 elevation 模块 // @use 'material-web/tokens'; // @use 'material-web/elevation'; // .surface { @include elevation.theme((level: 5, shadow-color: #006A6A)); }(thememixin 的 token 白名单定义在 tokens/_md-comp-elevation.scss 的$supported-tokens中,传入白名单之外的 token 会在编译期直接@error报错。)
API 一览
<md-elevation>的公共 API 极为精简,不暴露任何属性(property)、属性(attribute)与方法,所有能力都通过 CSS 自定义属性对外提供:
--md-elevation-level:取整数值 0~5,控制高度等级,默认0;--md-elevation-shadow-color:控制阴影颜色,默认引用--md-sys-color-shadow。
配合使用的还有宿主上的两个标准 CSS 属性:transition-duration与transition-easing-function(组件用transition-timing-function的inherit完成继承),用于开启阴影动画。
测试方面,elevation/elevation_test.ts 通过createTokenTests(MdElevation.styles)对组件的样式 token 做一致性校验,确保暴露的 token 与主题体系声明保持一致。
总结
- 是 M3 六档高度体系的 Web 实现:用
--md-elevation-level: 0~5控制,自动铺满并继承最近position: relative宿主的尺寸与圆角; - 静止用低档(0~+3),交互用高档(+4~+5):这是 Material 对高度体系的创造性约束,也是最容易出彩的设计决策点;
- 动画零成本:给宿主加
transition-duration/transition-easing-function,配合状态切换改变--md-elevation-level即可获得流畅的阴影过渡,因为底层阴影参数由 CSS 变量实时推导; - 主题化只碰颜色:两个 token 中
--md-elevation-shadow-color默认指向--md-sys-color-shadow,改一个系统变量即可全局换色; - 纯视觉、零负担:组件不拦截事件、无无障碍问题,天然适合作为任意表面的一层"投影叠加层"。
- UI组件
- 前端
- 设计系统
【免费下载链接】material-web
Material Design Web Components
相关推荐
Material Components Web Elevation 指南:阴影体系、Sass Mixin 与 Elevation Overlay 实战
Material Components Web Elevation 指南:阴影体系、Sass Mixin 与 Elevation Overlay 实战 本文围绕
前端UI组件设计系统超实用Markdown-Cheatsheet图片技巧:主题适配与排版进阶指南
超实用Markdown Cheatsheet图片技巧:主题适配与排版进阶指南 Markdown Cheatsheet是一款终极的Markdown语法参考工具,提
如何掌握Material Design Lite阴影系统:Elevation与Depth设计终极指南
如何掌握Material Design Lite阴影系统:Elevation与Depth设计终极指南 Material Design Lite是一个轻量级的前端
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考