资讯详情

资讯详情

Material Components Web 形状系统(Shape)完全指南:圆角体系、Sass 变量与 radius 混入深度解析

Material Components Web 形状系统Shape完全指南圆角体系、Sass 变量与 radius 混入深度解析【免费下载链接】material-components-webModular and customizable Material Design UI components for the web项目地址: https://gitcode.com/gh_mirrors/ma/material-components-web本文以material/shape包Material Components for the web 的形状系统为核心系统讲解其设计意图、安装方式、Sass 变量与 CSS 自定义属性、四个核心 Sass 函数以及radius()混入的使用方法与底层实现原理并结合固定高度、动态高度、指定角落与组件主题化四类实战场景帮助读者在按钮、卡片、抽屉等组件上精准应用圆角形状。什么是 Material 形状系统在 Material Design 的设计语言中形状Shape用于引导注意力、标识组件、传达状态并表达品牌个性。material/shape是 material-components-web 中独立封装形状工具的包它为所有其他组件提供统一的圆角radius处理能力是按钮、卡片、抽屉、输入框等组件主题化的基础设施之一。该包当前的唯一支持形状是圆角rounded cornersREADME 与源码均明确标注了这一点见 packages/mdc-shape/README.md源码中resolve-radius()对非rounded的 family 会直接抛出错误error mdc-shape: Invalid shape family: #{$family}. Only rounded is supported.;因此本文所有讨论都围绕圆角展开不涉及剪角cut corners、凹陷concave等其他形状家族。安装与引入作为独立 npm 包安装命令为npm install material/shape在 package.json 中可以看到该包版本为 14.0.0与仓库其他包保持一致声明了 MIT 许可并依赖以下模块material/feature-targeting特性定位编译期裁剪未启用特性的样式material/rtlRTL从右到左语言环境下的样式翻转material/theme主题变量与 CSS 自定义属性输出tslibTypeScript 运行时辅助库在 SCSS 中引入整个形状模块use material/shape;模块入口 packages/mdc-shape/_index.scss 分别转发了variables、mixins与functions三个子模块因此一次use即可同时获得变量、混入与函数。兼容性说明仓库同时保留了_mixins.scss、_functions.scss、_variables.scss三个文件它们仅做forward ./shape转发并在注释中标注deprecated建议新代码直接使用_shape.scss模块即use material/shape。形状类别与 Sass 变量Material 形状系统把组件划分为small小、medium中、large大三个类别。覆盖下面的 Sass 变量会一次性改变对应类别下所有组件的圆角。变量描述默认值$small-component-radius小尺寸组件的圆角半径4px$medium-component-radius中尺寸组件的圆角半径4px$large-component-radius大尺寸组件的圆角半径0这些变量的定义位于 packages/mdc-shape/_shape.scss 顶部// Shape categories $small-component-radius: 4px !default; $medium-component-radius: 4px !default; $large-component-radius: 0 !default;变量使用!default声明意味着只有当调用方尚未定义同名变量时才会生效这保证了使用者可以通过 Sass 变量覆盖机制安全地全局定制形状。定义之后这三个类别值还会被注册为主题键theme keys以便与主题系统统一协作include keys.set-values( ( small: $small-component-radius, medium: $medium-component-radius, large: $large-component-radius, ), $options: (custom-property-prefix: shape) );此外源码还提供两个辅助函数用于操作类别键is-shape-key($radius)判断传入值是否为small/medium/large之一get-shape-keys()返回全部形状类别键的列表。组件属于哪个类别可参考 Material Design 官方 Shape 指南对组件的归类说明类别选择会直接影响最终渲染出来的圆角观感。CSS 自定义属性除了 Sass 变量形状系统还对外暴露一组 CSS 自定义属性方便在运行时例如通过 JavaScript 或内联样式动态调整圆角。CSS 自定义属性描述默认值--mdc-shape-small小尺寸组件的圆角半径4px--mdc-shape-medium中尺寸组件的圆角半径4px--mdc-shape-large大尺寸组件的圆角半径0这组自定义属性正是上文keys.set-values以shape为前缀注册的产物small、medium、large分别对应--mdc-shape-small、--mdc-shape-medium、--mdc-shape-large。⚠️重要限制不要在自定义属性中使用百分比值。因为shape.radius()在运行时无法解析百分比对应的组件高度百分比的解析必须依赖编译期传入的$component-height。源码中百分比到绝对值的转换发生在 Sass 编译阶段见下文resolve-radius()的_resolve-radius-percentage内部函数CSS 自定义属性在运行时并不能完成这一换算。Sass 函数详解形状模块提供了四个公开 Sass 函数它们分别负责半径值的解析、翻转、掩码与展开。下面结合 packages/mdc-shape/_shape.scss 的源码逐一说明。resolve-radius($radius, $component-height)返回某个形状类别large、medium、small解析后的半径值。如果传入的不是类别名则在该值合法数字或百分比时原样返回。$component-height在$radius可能为百分比时必须提供用于把百分比换算为绝对像素值。源码中的核心分支逻辑如下简化说明传入null直接返回null传入列表递归解析每个角落值列表长度必须为 14否则报错Radius must be between 1 and 4 values.传入形状类别键先通过keys.create-custom-property($radius)转为自定义属性再递归解析传入自定义属性 Map解析其 fallback 值并重新写回传入形状 Map含family与radius字段校验family必须为rounded随后解析radius字段其余情况视为数值若单位是%且提供了$component-height则调用内部函数换算为绝对值function _resolve-radius-percentage($percentage, $component-height) { // 50% 50再乘以高度百分比 $percentage: math.div($percentage, $percentage * 0 1); return $component-height * math.div($percentage, 100); }例如resolve-radius(50%, $component-height: 36px)的结果就是16px。flip-radius($radius)在 RTL从右到左语境下翻转半径值。$radius为 24 个角落值的列表翻转规则等价于把水平方向上的两对角互换4 值(a b c d)→(b a d c)3 值(a b c)→(b a b c)2 值(a b)→(b a)单值原样返回。若列表超过 4 个值函数会直接报错Invalid radius: ... is more than 4 values。mask-radius($radius, $masked-corners)接受一个半径数字或 24 个值的列表返回一个 4 值列表其中未被掩码$masked-corners中对应位为 0的角落被置为 0保留掩码位为 1 的角落值。$masked-corners必须是长度为 4 的列表否则报错。源码示例注释给出了三个直观用例// mask-radius(2px 3px, 1 1 0 0) 2px 3px 0 0 // mask-radius(8px, 0 0 1 1) 0 0 8px 8px // mask-radius(4px 4px 4px 4px, 0 1 1 0) 0 4px 4px 0该函数在实现上先调用unpack-radius展开为 4 值再按掩码逐位决定保留或清零。unpack-radius($radius)展开border-radius的简写值13 个值的列表如果传入的是 4 值列表则原样返回。它内部直接复用了主题模块的css.unpack-value()function unpack-radius($radius) { return css.unpack-value($radius); }展开规则与 CSSborder-radius简写一致// unpack-radius(4px) 4px 4px 4px 4px // unpack-radius(4px 2px) 4px 2px 4px 2px // unpack-radius(4px 2px 2px) 4px 2px 2px 2px // unpack-radius(4px 2px 0 2px) 4px 2px 0 2pxradius() 混入核心 API 与源码原理radius($radius, $rtl-reflexive)是形状模块最核心的混入所有其他组件都通过它把圆角应用到对应角落。参数描述$radius单个值或最多 4 个角落值的列表$rtl-reflexive设为true时在 RTL 语境下翻转半径默认false混入的完整签名在源码中还支持$component-height与$query两个可选参数packages/mdc-shape/_shape.scss 的radius混入其中$query用于特性定位裁剪。其核心执行流程可以拆解为四步计算是否需要翻转仅当$rtl-reflexive为 true 且$radius是多个值的列表时即$has-multiple-corners为 true才认为需要翻转——注释明确写道即使开启了$rtl-reflexive只要半径明显是对称的就不输出 RTL 样式解析半径调用resolve-radius()把类别名、百分比等统一解析为最终值单值场景$radius不是多角列表时直接输出一条border-radius属性通过theme.property支持自定义属性输出多值场景unpack-radius展开为 4 值后分别输出border-top-left-radius、border-top-right-radius、border-bottom-right-radius、border-bottom-left-radius四条属性若需要翻转再在rtl.rtl包裹块中用flip-radius()输出翻转后的四角值。从源码结构看radius混入借助material/theme的theme.property输出属性这意味着当传入自定义属性 Map 时生成结果仍能保留 CSS 自定义属性的引用从而与--mdc-shape-*体系无缝衔接。四类实战场景1. 固定高度组件如按钮固定高度组件如标准按钮需要把百分比圆角换算成绝对值因此必须传入组件高度use material/button; use material/shape; include shape.radius($radius, $component-height: button.$height);其中button.$height是标准按钮的高度$radius是形状大小。shape.radius()会基于组件高度把百分比单位解析为绝对半径值。按钮组件内部正是这样工作的在 packages/mdc-button/_button-shared-theme.scss 中shape-radius()混入通过_shape-radius-with-height()最终调用shape.radius()并默认使用$density-default-scale对应的高度。2. 动态高度组件如卡片动态高度组件如卡片无法预知高度因此$radius只能是绝对值include shape.radius($radius);这里的$radius只能传绝对长度如8px不能传百分比——因为缺少固定高度作为换算基准。3. 指定特定角落如抽屉只给部分角落应用圆角时传入 14 值的列表并开启 RTL 反射。抽屉只在右侧显示圆角的经典写法include shape.radius(0 $radius $radius 0, $rtl-reflexive: true);该写法只定制右上角与右下角当页面处于 RTL 语境时shape.radius()会自动把半径翻转到左侧保证镜像布局下视觉对称。4. 组件级主题化以按钮为例实际开发中最常见的是通过各组件的专属混入间接使用形状系统。以按钮为例给按钮应用 50% 药丸形状use material/button; .my-custom-button { include button.shape-radius(50%); }这里的 50% 会被按钮组件的内部实现结合按钮高度解析为半高半径从而形成药丸造型也可以传入绝对值如8px。使用建议Shape API 通常不直接调用而是经由各组件自己的混入间接使用——组件混入会负责设置高度、并把圆角应用到该组件所有适用变体的正确角落使用者只需关注传入的半径值即可。源码与测试导览核心实现packages/mdc-shape/_shape.scss 包含全部变量、函数与混入packages/mdc-shape/_index.scss 是模块入口。兼容转发层packages/mdc-shape/_mixins.scss、packages/mdc-shape/_functions.scss、packages/mdc-shape/_variables.scss 均为已标记 deprecated 的转发文件另有对应的*.import.scss旧式引入入口。单元测试packages/mdc-shape/test/shape.test.scss 使用true断言框架重点覆盖resolver($shape)函数验证null时四角全为null、单值展开到全部角落、1/2/3/4 值列表分别映射到start-start、start-end、end-end、end-start逻辑角落的映射规则。特性定位测试packages/mdc-shape/test/feature-targeting-any.test.scss 与 packages/mdc-shape/test/mdc-shape.scss.test.ts 共同验证当查询条件为feature-targeting.any()时不输出任何 CSS从而保证样式可按需裁剪。总结与注意事项当前形状系统仅支持圆角传入其他 shape family 会在编译期报错三个类别small / medium / large通过 Sass 变量与 CSS 自定义属性双通道可调默认分别为4px、4px、0CSS 自定义属性禁止使用百分比百分比解析依赖编译期传入的$component-height优先通过组件自身的形状混入如button.shape-radius()使用形状系统而不是直接调用shape.radius()$rtl-reflexive仅在多角值列表且确实不对称时才产生 RTL 翻转样式对称半径不会产生冗余输出。【免费下载链接】material-components-webModular and customizable Material Design UI components for the web项目地址: https://gitcode.com/gh_mirrors/ma/material-components-web创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →