Carbon Design System 排版基石:@carbon/type 的 Sass 使用指南与源码级原理解析
【免费下载链接】carbonA design system built by IBM项目地址: https://gitcode.com/GitHub_Trending/carbo/carbon
本文基于 IBM Carbon Design System(当前仓库 carbo/carbon)中
@carbon/type包的 Sass 官方文档 编写。@carbon/type是 Carbon Design System 的排版基础包,封装了 IBM Design Language 的字阶(Type Scale)、字体(IBM Plex 系列)与整套排版设计令牌(Type Tokens),并内置了h1、h2、p等常见元素的有主见默认样式。读完本文,你将掌握@carbon/type的全部 Sass 用法:快速接入、四个核心 Mixin、类型令牌与工具类的选用、$prefix配置,以及其字阶公式、流式排版(Fluid Type)与 CSS 自定义属性等底层实现原理,可直接上手把它接入自己的项目。
一、@carbon/type 是什么
@carbon/type是 Carbon Design System 的排版包(当前仓库版本为11.67.0,见 packages/type/package.json),它提供三样核心能力:
- 字阶(Type Scale):一套从 12px 到 92px、共 23 个步进的字号系统;
- 字体(Fonts):IBM Plex 系列字体族及其回退栈(fallback stack);
- 排版设计令牌(Type Tokens):如
productive-heading-01、body-02等,每个令牌包含font-size、font-weight、line-height、letter-spacing的完整声明组合。
除此之外,它还带来"开箱即用"的默认样式:通过default-typeMixin 可以直接为h1~h6、p、a、em等 HTML 元素应用设计系统认可的排版,无需逐个手动书写。
从构建层面看,该包同时提供 JavaScript API(src/index.ts,构建产物为lib/index.js、es/index.js)与 Sass 入口(index.scss,并在package.json中通过"sass": "index.scss"声明),本文聚焦其 Sass 侧能力。
二、快速开始:接入 @carbon/type
2.1 安装
@carbon/type是独立发布的 npm 包,与@carbon/layout(提供间距、字号 rem 换算)和@carbon/grid(提供断点系统)配合工作,这两者也是它的直接依赖(见 packages/type/package.json 的dependencies字段)。安装命令:
npm install @carbon/type # 或 yarn add @carbon/type2.2 最小使用示例
在 Sass 中使用现代模块系统@use引入,并调用四个常用 Mixin:
@use '@carbon/type'; // 包含排版 reset:html 字号、body 字体与抗锯齿、code 等基线样式 @include type.reset(); // 包含默认排版样式,作用于 h1, h2, h3 等元素 @include type.default-type(); // 包含排版相关的工具类(utility classes) @include type.type-classes(); .selector { // 在任意选择器中套用某个类型令牌 @include type.type-style('productive-heading-01'); }其中@use '@carbon/type'会加载包的 Sass 入口 packages/type/index.scss,该入口通过@forward依次暴露了 7 个子模块:scss/prefix、scss/font-family、scss/scale、scss/reset、scss/styles、scss/classes、scss/default-type。因此上述四个 Mixin 均可用type.前缀直接调用。
2.3 仓库内真实使用参考
仓库自带的示例工程 packages/type/examples/preview/src/styles.scss 展示了完整实践:先通过@use '@carbon/styles/scss/config' with (...)配置字体路径与需要加载的字体(含阿拉伯、梵文、希伯来、泰文等多语言 IBM Plex 字体),再@use '@carbon/type' as *;,随后直接@include reset();、@include type-classes();,并基于$type-scale循环生成.type-scale-1~.type-scale-23演示类。
三、核心 API 详解
3.1 四个核心 Mixin
| Export(导出) | 说明 |
|---|---|
@mixin type-classes | 生成排版工具类的 CSS(字体族、字重、斜体、各令牌) |
@mixin reset | 生成 Carbon Design System 的基础排版基线样式 |
@mixin default-type | 为h1~h6、p、a等元素生成默认排版样式 |
@mixin type-style | 在任意选择器内输出某个类型令牌的全部声明 |
reset的源码细节:见 packages/type/scss/_reset.scss。它接收两个可选参数:
@mixin reset( $body-font-family: font-family('sans'), $mono-font-family: font-family('mono') )输出内容为:
html { font-size: 100%; }—— 保证 rem 换算基准;body使用sans字体族、regular(400)字重,并开启-moz-osx-font-smoothing: grayscale、-webkit-font-smoothing: antialiased、text-rendering: optimizeLegibility以优化渲染;code使用等宽字体mono;strong提升为semibold(600)字重。
default-type的映射关系:见 packages/type/scss/_default-type.scss。它把语义元素映射到设计令牌,无需记忆字号即可获得规范排版:
| 元素 | 令牌 |
|---|---|
h1 | heading-06 |
h2 | heading-05 |
h3 | heading-04 |
h4 | heading-03 |
h5 | heading-02 |
h6 | heading-01 |
p | body-02 |
同时它还为a设置链接色var(--cds-link-primary, #0062fe)(优先读取 CSS 自定义属性,缺失时回退到 IBM 蓝#0062fe),为em设置斜体。注意:a与em使用--#{$prefix}-link-primary动态拼接,因此会跟随$prefix配置变化。
type-classes的生成逻辑:见 packages/type/scss/_classes.scss。它通过三个@each循环遍历$font-families、$font-weights与$tokens三张映射表,分别生成字体族、字重、以及每个令牌对应的工具类(见下节)。
3.2 类型工具类(Type classes)
type-classesMixin 会输出一批工具类,可直接用于 HTML 元素:
| 类名 | 说明 |
|---|---|
.cds--type-{font-family} | 设置font-family。可选值:mono、sans、sans-condensed、sans-arabic、sans-devanagari、sans-hebrew、sans-jp、sans-kr、sans-thai-looped、sans-thai、serif |
.cds--type-{font-weight} | 设置font-weight。可选值:light(300)、regular(400)、semibold(600) |
.cds--type-italic | 设置font-style: italic |
.cds--type-{token} | 将元素样式设置为对应类型令牌,如.cds--type-productive-heading-01 |
这些字体族与字重的完整定义位于 packages/type/scss/_font-family.scss:$font-families映射中每个字体族都带完整的回退栈,例如sans展开为'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, '.SFNSText-Regular', sans-serif;$font-weights则定义了light: 300、regular: 400、semibold: 600三档推荐字重。
3.3 完整令牌清单(Token API)
下表列出了@carbon/type导出的全部类型令牌变量,均以!default声明(即允许你在@use ... with (...)之外通过 Sass Modules 覆写,或在使用前重新赋值覆盖)。它们以 Map 形式存在,每个值包含font-size、font-weight、line-height、letter-spacing(含breakpoints的为流式令牌,见 4.3 节)。
| 令牌变量 | !default |
|---|---|
$label-01、$legal-02、$helper-text-01、$helper-text-02 | ✅ |
$body-short-01、$body-compact-01、$body-long-01、$body-01 | ✅ |
$body-short-02、$body-compact-02、$body-long-02、$body-02 | ✅ |
$code-01、$code-02 | ✅ |
$heading-01、$productive-heading-01、$heading-compact-01 | ✅ |
$heading-02、$productive-heading-02、$heading-compact-02 | ✅ |
$productive-heading-03、$heading-03 | ✅ |
$productive-heading-04、$heading-04 | ✅ |
$productive-heading-05、$heading-05 | ✅ |
$productive-heading-06、$heading-06 | ✅ |
$productive-heading-07、$heading-07 | ✅ |
$expressive-heading-01、$expressive-heading-02、$expressive-heading-03、$fluid-heading-03 | ✅ |
$expressive-heading-04、$fluid-heading-04、$expressive-heading-05、$fluid-heading-05、$expressive-heading-06、$fluid-heading-06 | ✅ |
$expressive-paragraph-01、$fluid-paragraph-01 | ✅ |
$quotation-01、$fluid-quotation-01、$quotation-02、$fluid-quotation-02 | ✅ |
$display-01、$fluid-display-01、$display-02、$fluid-display-02、$display-03、$fluid-display-03、$display-04、$fluid-display-04 | ✅ |
所有令牌被统一聚合进$tokens映射表(见 packages/type/scss/_styles.scss),该表同时是type-styleMixin 与type-classes工具类生成器的数据来源。命名上有两条规律值得注意:
- productive / expressive / fluid 三大家族:
productive-*面向紧凑型产品界面,行高更小;expressive-*面向营销与叙事场景,行高更大且带响应式断点;fluid-*是expressive-*的别名,强调随视口连续缩放; - 新旧令牌并存:如
body-short-01/body-long-01(V10 遗留)与body-compact-01/body-01(V11 令牌)在$tokens中同时存在,部分旧令牌(如$caption-01、$caption-02、$helper-text-01)在源码中被标记为@deprecated,新项目应优先选用 V11 令牌。
四、配置项:$prefix 与 CSS 自定义属性前缀
@carbon/type支持通过 Sass Modules 的with语法进行配置:
@use '@carbon/type' with ( $prefix: 'custom-prefix' );配置项完整列表如下:
| 选项 | 说明 | 默认值 |
|---|---|---|
$prefix | 用于选择器、CSS 自定义属性等的前缀 | 'cds' |
$prefix会影响三处输出(见 packages/type/scss/_prefix.scss):
- 工具类名:
.cds--type-sans变为.custom-prefix--type-sans; - CSS 自定义属性名:
type-style输出形如font-size: var(--cds-productive-heading-01-font-size, ...)的声明,前缀同样随之变化; default-type中的链接色:var(--cds-link-primary, #0062fe)。
此外_prefix.scss还声明了第二个配置变量$custom-property-prefix: 'cds' !default,它专门控制 CSS 自定义属性前缀,可由内部的configure($values)Mixin 单独设置,便于在工具类前缀与自定义属性前缀需要分离的场景(如与@carbon/themes协同)下使用。
五、源码级原理剖析
5.1 字阶公式:从 12px 到 92px
@carbon/type的字阶不是拍脑袋定死的数值,而是由一条递推公式生成(见 packages/type/scss/_scale.scss):
Yn = Yn-1 + {INT[(n-2)/4] + 1} * 2其中Y1 = 12px。该公式的含义是:每跨过一个步进,字号在前一步基础上增加 2px、4px、6px…… 的阶梯增量(增量每 4 步提升 2px),使得字号在大尺寸段拉开间距、小尺寸段保持细腻,从 12px 一路递增到 92px,共 23 个步进。每个步进再通过@carbon/layout的to-rem转换为 rem 单位存入$type-scale列表。相关函数与 Mixin:
// 取第 $step 步的字号(rem) $fs: type-scale(8); // 或直接在选择器中设置 .selector { @include type-scale(8); // 等价于 @include font-size(8); }5.2 type-style:令牌是如何输出的
type-styleMixin 的核心逻辑位于 packages/type/scss/_styles.scss:
@mixin type-style($name, $fluid: false, $breakpoints: gridconfig.$grid-breakpoints) { @if not map.has-key($tokens, $name) { @error 'Unable to find a token with the name: `#{$name}`'; } $token: map.get($tokens, $name); // 开启流体且令牌定义了 breakpoints 时,走流体排版 @if $fluid == true and map.has-key($token, 'breakpoints') { @include fluid-type($token, $breakpoints); } @else { // 否则输出 CSS 自定义属性 + 回退值 @include custom-properties($name, $token); } }要点一:令牌名错误会直接编译报错(@error),避免静默失败。要点二:默认输出的是CSS 自定义属性而非裸属性值,例如:
.selector { font-size: var(--cds-productive-heading-01-font-size, 0.875rem); font-weight: var(--cds-productive-heading-01-font-weight, 600); line-height: var(--cds-productive-heading-01-line-height, 1.28572); letter-spacing: var(--cds-productive-heading-01-letter-spacing, 0.16px); }这一设计让主题系统可以在运行时通过覆盖自定义属性实现换肤,而编译期回退值保证了不依赖运行时变量时的可用性。仓库测试 packages/type/tests/scss-test.js 专门验证了这一行为:断言每个属性值都包含var(--且回退值与 JS 侧令牌productiveHeading01对应键一致。
5.3 流式排版(Fluid Type)
对于定义有breakpoints键的令牌(如$expressive-heading-03、$display-04等),type-style($name, true)会启用流体排版:font-size不再由断点阶梯切换,而是通过calc()依据视口宽度连续计算:
.selector { @include type-style('expressive-heading-03', true); }其原理(实现见_styles.scss的fluid-type与fluid-type-size,参考了 CSS-Tricks 的 fluid typography 方案):以当前断点宽度为min-vw、下一个含流体定义的断点宽度为max-vw,以两个断点的字号为min-font-size/max-font-size,输出形如font-size: calc(min + (max - min) * ((100vw - min-vw) / (max-vw - min-vw)))的插值公式。行高则使用百分比相对值,以适配动态字号。源码注释特别提醒:流体排版应谨慎用于固定宽度容器,因为字号完全取决于视口。同时,无breakpoints的令牌即使传true也会回退为普通静态输出。
5.4 与其它包的协作
@carbon/type处于 Carbon 设计令牌生态的中层:
- 依赖
@carbon/layout:负责to-rem换算等基础工具; - 依赖
@carbon/grid:提供断点系统($grid-breakpoints、breakpoint()、breakpoint-next()),供流体排版与令牌断点使用; - 与
@carbon/themes约定共享 CSS 自定义属性前缀机制(源码中留有 TODO,计划将custom-propertiesMixin 抽取为两包共用模块)。
六、最佳实践小结
- 三段式引入:
reset()+default-type()建立全局排版基线,type-classes()按需输出工具类(体积敏感时可改为只引入自己用到的type-style); - 优先用令牌而非手写数值:所有字号、行高、字重都通过令牌表达,保证与设计系统一致且可被主题覆盖;
- 区分静态与流体:正文、表格等密集内容用
productive-*/body-*静态令牌;营销头图、大标题用expressive-*并开启$fluid: true; - 注意前缀一致性:自定义
$prefix时,需同步确保 HTML 中使用的工具类名(如.cds--type-sans)与新前缀匹配; - 多语言场景:阿拉伯、梵文、希伯来、泰文、日文、韩文等字体族已内置回退栈,仅需按示例工程方式在
@carbon/styles的$fonts配置中开启对应字体加载。
相关文档与源码入口:Sass 文档、包入口、令牌与流体实现、字阶实现、字体族与字重、Sass 测试。
【免费下载链接】carbonA design system built by IBM项目地址: https://gitcode.com/GitHub_Trending/carbo/carbon
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考