为组件添加样式
为了让你的组件拥有 Lightning Experience 的外观和体验,请使用 Lightning Design System(SLDS)和 Lightning 基础组件。在 lightning 命名空间中使用基础组件时,你将自动获得 SLDS 样式。本章将全面介绍 LWC 样式系统。
SLDS 1 与 SLDS 2 对比
SLDS 2 在 Spring '25 引入,默认主题为 Salesforce Cosmos。原始 SLDS 现称为 SLDS 1(默认主题:Lightning Blue)。
关键差异
| 特性 | SLDS 1 | SLDS 2 |
|---|---|---|
| 网站 | v1.lightningdesignsystem.com | lightningdesignsystem.com |
| 默认主题 | Lightning Blue | Salesforce Cosmos |
| 设计令牌 | 支持(--lwc- 前缀) | 不支持 |
| 组件级样式钩子 | 支持(--slds-c-*) | 暂不支持 |
| 全局样式钩子 | 可用(颜色类) | 主要样式机制 + 语义 UI 颜色 |
| 组件蓝图 | 相同(仅在 SLDS 1 站点上) | |
迁移工具
- SLDS Linter(新):分析代码是否符合 SLDS 2 规则,支持跨仓库批量自动修复
- SLDS Validator(VS Code):支持 SLDS 1 + 2,自动安装(Salesforce Extension Pack 的一部分)
重要:如果组件使用 --slds-c-* 组件级钩子 → 暂时留在 SLDS 1。用全局样式钩子替换设计令牌。
Lightning 基础组件 —— 样式优先级
基础组件自动提供 SLDS 样式。按优先级从高到低自定义:
1. 设计变体(variant 属性)
<lightning-button variant="brand" label="Submit"></lightning-button>
<!-- brand, neutral, destructive, success, inverse... -->
2. SLDS 工具类
<lightning-button class="slds-m-left_medium" label="Cancel"></lightning-button>
3. 样式钩子(Styling Hooks)
:host {
--slds-c-button-brand-color-background: var(--slds-g-orange-70);
}
自定义 CSS 类(正确做法)
/* 错误 —— 覆盖 SLDS 类 */
.slds-button { padding: 16px; } /* 不要这样做! */
/* 正确 —— 创建自定义类,提供回退值 */
.my-button-padding {
padding: var(--slds-g-spacing-4, var(--lwc-spacingMedium, 1rem));
}
<button class="slds-button my-button-padding">
关键原则:不要依赖基础组件的内部标记(可能变更);不要覆盖 .slds-* 类;不要使用 !important;不要重载选择器;使用 SLDS 2 全局钩子时始终提供 SLDS 1 回退值。
SLDS 样式钩子 —— 组件级别
组件样式钩子(--slds-c-*)针对特定组件,仅在 SLDS 1 中可用。
自定义品牌按钮颜色
<!-- myBaseButton.html -->
<lightning-button variant="brand" label="Submit"></lightning-button>
/* myBaseButton.css */
:host {
--slds-c-button-brand-color-background: var(--slds-g-purple-30);
--slds-c-button-brand-color-border: var(--slds-g-purple-30);
}
工作原理
- 每个基础组件为其元素暴露 CSS 自定义属性
- 在
:host上设置属性值来自定义外观 - 更改仅影响该组件实例
- 在 SLDS 1 站点每个蓝图上查看可用的样式钩子
支持限制
- Toast:
lightning/platformShowToastEvent不支持--slds-c-toast-*(改用lightning/toast) - Tooltip:
lightning-helptext不支持--slds-c-tooltip-* - 链接和表单元素:不支持通过自定义属性进行样式设置
SLDS 全局样式钩子与设计令牌
全局钩子(--slds-g-*)应用于所有组件,在 SLDS 1 和 SLDS 2 中均受支持。
全局间距钩子
/* 替换设计令牌 */
margin-right: var(--slds-g-spacing-2);
/* 以前是:var(--lwc-spacingSmall); */
设计令牌(SLDS 2 中已废弃)
/* 仅 SLDS 1 —— 使用 --lwc- 前缀 */
div { margin-right: var(--lwc-spacingSmall); }
/* 替换为全局钩子: */
div { margin-right: var(--slds-g-spacing-2); }
注意:令牌在编译时替换为实际值 —— 运行时不能使用getPropertyValue()或setPropertyValue()。只有标记为 Global Access 的令牌可用于 LWC。
自定义 Aura 令牌(--c- 前缀)
/* LWC CSS 中使用 --c- 前缀 */
color: var(--c-myBackgroundColor);
建议:优先使用全局样式钩子而非 Aura 令牌,以符合 WCAG 2.1 颜色对比度标准。
从 SLDS 蓝图创建组件
当没有对应的基础组件时,从最接近的 SLDS 蓝图构建。以 scoped notification 为例:
步骤 1:复制基础变体标记
<div class="slds-scoped-notification slds-media slds-media_center
slds-scoped-notification_light" role="status">
<!-- SLDS 标记 -->
</div>
步骤 2:用基础组件替换标准 HTML
<lightning-icon icon-name="utility:info"
alternative-text="info" size="small"></lightning-icon>
步骤 3:将内容移至 JS,绑定到模板
@api message = "Your message here";
// 模板中:<p>{message}</p>
步骤 4:用 getter 创建主题变体
get scopedNotificationClass() {
let cls = "slds-scoped-notification slds-media slds-media_center";
if (this.theme === "light") cls += " slds-scoped-notification_light";
if (this.theme === "dark") cls += " slds-scoped-notification_dark";
return cls;
}
// 模板:<div class={scopedNotificationClass}>
步骤 5:绑定动态属性
get iconVariant() {
return this.theme == 'dark' ? 'inverse' : null;
}
重要:蓝图的标记会成为你的代码 —— SLDS 更新不会自动应用。而基础组件会随 SLDS 更新自动升级。检查蓝图页面上是否有 "Lightning Component" 按钮——如果有,说明基础组件已存在。
CSS 样式表 —— Shadow DOM 封装
LWC 使用 Shadow DOM 实现 CSS 封装——组件样式表中的样式仅作用于该组件。
Shadow DOM 规则
- 父组件样式不渗透到子组件内部
- 父组件可以将子组件作为单个元素设置样式:
c-child { border: 2px solid red; } - 子组件通过
:host选择器设置自身样式
:host 选择器
/* child.css */
:host {
display: block;
background: yellow;
}
:host(.active) {
background-color: lightgreen;
}
/* 用法:<c-child class="active"> */
CSS 级联与优先级
- Shadow DOM 中应用标准级联规则
- 类选择器 → 更高优先级;相同优先级时后定义的胜出
- 不支持 ID 选择器(运行时会转换为全局唯一值)
CSS 属性继承
- 可继承属性(color、font)→ 穿透 Shadow DOM 边界
- 不可继承属性(border)→ 使用初始值
- CSS 自定义属性始终穿透 Shadow DOM
CSS 支持限制
- 不支持
:host-context()伪类 - 不支持
::part伪元素 - 不支持 ID 选择器
- 公共属性不反映到 HTML 属性(使用 class 或 data-* 代替)
性能影响:作用域 CSS 会增加每个元素的作用域属性,每个选择器链都会被作用域化。更多 CSS = 更多带宽、解析和重计算时间。在大型应用中谨慎使用。
Stylesheets 属性与自定义样式钩子
分配多个样式表 —— static stylesheets
import headerStyles from "./header-styles.css";
import buttonStyles from "./button-styles.css";
export default class Example extends LightningElement {
static stylesheets = [headerStyles, buttonStyles];
}
加载顺序:myComponent.css(隐式,始终第一)→ header-styles.css → button-styles.css
子类合并
class Subclass extends Superclass {
static stylesheets = [...super.stylesheets, subclassStylesheet];
}
创建你自己的样式钩子
:host {
--important-color: red;
}
.important {
color: var(--important-color);
}
带回调值的主题钩子
.light {
background-color: var(--light-theme-bg, lightcyan);
color: var(--light-theme-text, darkblue);
}
.dark {
background-color: var(--dark-theme-bg, darkslategray);
color: var(--dark-theme-text, ghostwhite);
}
自定义钩子的优势
- 消费者在更高 DOM 级别设置值 —— 无需了解实现细节
- CSS 自定义属性是继承的,自动穿透 Shadow DOM
- 将钩子作为组件公共 API 的一部分进行文档化
- 使主题化和品牌重塑变得简单
- 使用
var()提供回退值
反模式 —— 不要这样做
1. 为基础组件的渲染 HTML 设置样式
/* 错误 —— 针对内部标记 */
.acme-box .slds-combobox__input { }
/* 内部类在任何版本中都可能发生变化!*/
2. 直接覆盖 SLDS 类
/* 错误 —— 覆盖 SLDS 选择器 */
.slds-button_brand { background-color: purple; }
.slds-button { padding: 16px; }
3. 使用精确字符串匹配的 querySelector
// 错误 —— 空白被压缩后匹配失败
document.querySelector(".slds-m-around_medium highlight yellow");
// 正确 —— 忽略空白的写法
document.querySelector(".slds-m-around_medium.highlight.yellow");
// 注意:空 class="" 和 style="" 在渲染时会被移除
4. 依赖 CSS 作用域令牌
/* 错误 —— 依赖内部属性 */
[c-cmp_cmp-host] { }
/* API 59.0+ 后令牌被混淆为 lwc-2s44vctlls4-host 格式
使用 lwc:ref 代替 querySelector */
5. 重载选择器
/* 错误 —— 过于具体 / 使用 !important */
body.container > div.sidebar > article.card { }
.button { margin-bottom: 18px !important; }
支持的做法
设计变体(variant)→ SLDS 工具类(class)→ 样式钩子(CSS 自定义属性)→ 自定义 CSS 类配合 SLDS → :host 选择器 → CSS @import 共享样式
共享 CSS 样式规则
1. 创建 CSS 模块(无需 HTML 或 JS)
cssLibrary/
├── cssLibrary.css
└── cssLibrary.js-meta.xml
/* cssLibrary.css */
h1 { font-size: xx-large; }
.warning { color: orange; }
2. 在组件 CSS 中导入
/* myComponent.css */
@import "c/cssLibrary";
/* 其他本地样式 */
关键规则
- @import 格式:
"namespace/moduleName" - LWC 不支持 @import 中的媒体查询
- Lightning Locker:仅 c 和 lightning 命名空间
- LWS:任何命名空间均可访问
- 导入的样式与本地样式一样进行级联
优势
- 所有组件外观一致
- 共享样式的单一真相源 —— 一次更新,处处应用
- 与 SLDS 样式钩子配合使用,实现集中式主题化
感谢阅读本指南。如需继续学习,请参阅下一章:组件组合。