样式

你的组件的模板会被渲染到其 shadow root 中。你添加到组件中的样式会自动被 限定作用域 到 shadow root,并且只影响组件 shadow root 中的元素。

Shadow DOM 为样式提供了强大的封装。如果 Lit 不使用 Shadow DOM,你就必须非常小心,不要意外地为组件外部的元素(无论是组件的祖先还是子元素)添加样式。这可能需要编写冗长、难以使用的类名。通过使用 Shadow DOM,Lit 确保你编写的任何选择器只应用于 Lit 组件的 shadow root 中的元素。

你可以使用标记模板字面量 css 函数在静态 styles 类字段中定义限定作用域的样式。以这种方式定义样式可以获得最佳性能:

你添加到组件中的样式使用 shadow DOM 进行 作用域限定。要快速了解,请参见 Shadow DOM

静态 styles 类字段的值可以是:

  • 单个标记模板字面量。

  • 标记模板字面量数组。

静态 styles 类字段_几乎总是_向组件添加样式的最佳方式,但有些用例无法通过这种方式处理——例如,每个实例自定义样式。有关添加样式的其他方式,请参见在模板中定义限定作用域的样式

静态样式应用于组件的所有实例。CSS 中的任何表达式都只评估一次,然后在所有实例中重复使用。

对于基于树的或每个实例的样式自定义,请使用 CSS 自定义属性来允许元素主题化

为了防止 Lit 组件评估潜在的恶意代码,css 标签只允许嵌套表达式本身是 css 标记的字符串或数字。

这个限制存在是为了保护应用程序免受安全漏洞的影响,这些漏洞可能会从不受信任的来源(如 URL 参数或数据库值)注入恶意样式,甚至是恶意代码。

如果你必须在 css 字面量中使用一个不是 css 字面量的表达式,并且你确信该表达式来自完全可信的来源(如你自己代码中定义的常量),那么你可以使用 unsafeCSS 函数包装该表达式:

**只对受信任的输入使用 unsafeCSS 标签。**注入未经过滤的 CSS 是一个安全风险。例如,恶意 CSS 可以通过添加指向第三方服务器的图片 URL 来"回传信息"。

使用标记模板字面量数组,组件可以继承超类的样式,并添加自己的样式:

你也可以使用 super.styles 在 JavaScript 中引用超类的样式属性。如果你使用 TypeScript,我们建议避免使用 super.styles,因为编译器并不总是正确转换它。如示例所示,显式引用超类可以避免这个问题。

在编写打算在 TypeScript 中被子类化的组件时,static styles 字段应该显式地声明为 CSSResultGroup 类型,以允许用户使用数组覆盖 styles

你可以通过创建导出标记样式的模块在组件之间共享样式:

然后你的元素可以导入样式并将它们添加到其静态 styles 类字段中:

CSS 的 Unicode 转义序列是一个反斜杠后跟四个或六个十六进制数字:例如,\2022 表示一个项目符号字符。这与 JavaScript 已弃用的_八进制_转义序列的格式类似,因此在 css 标记模板字面量中使用这些序列会导致错误。

有两种方法可以在样式中添加 Unicode 转义:

  • 添加第二个反斜杠(例如,\\2022)。
  • 使用以 \u 开头的 JavaScript 转义序列(例如,\u2022)。

本节简要介绍 shadow DOM 样式。

你添加到组件的样式可以影响:

Lit 模板默认渲染到 shadow 树中。限定到元素的 shadow 树的样式不会影响主文档或其他 shadow 树。同样,除了继承的 CSS 属性外,文档级样式不会影响 shadow 树的内容。

当你使用标准 CSS 选择器时,它们只匹配你的组件 shadow 树中的元素。这意味着你通常可以使用非常简单的选择器,因为你不必担心它们会意外地为页面的其他部分添加样式;例如:input*#my-element

你可以使用特殊的 :host 选择器为组件本身添加样式。(拥有或"托管" shadow 树的元素称为_宿主元素_。)

要为宿主元素创建默认样式,请使用 CSS 伪类 :host 和 CSS 伪类函数 :host()

  • :host 选择宿主元素。
  • :host(selector) 选择宿主元素,但仅当宿主元素匹配_selector_时。

请注意,宿主元素也可能受到 shadow 树外部样式的影响,因此你应该将 :host:host() 规则中设置的样式视为可以被用户覆盖的_默认样式_。例如:

你的组件可能接受子元素(就像 <ul> 元素可以有 <li> 子元素一样)。要渲染子元素,你的模板需要包含一个或多个 <slot> 元素,如使用 slot 元素渲染子元素中所述。

<slot> 元素在 shadow 树中充当占位符,用于显示宿主元素的子元素。

使用 CSS 伪元素 ::slotted() 来选择通过 <slot> 包含在模板中的子元素。

  • ::slotted(*) 匹配所有插槽元素。
  • ::slotted(p) 匹配插槽的段落。
  • p ::slotted(*) 匹配 <slot> 是段落元素的后代的插槽元素。

请注意,只有直接插槽的子元素可以使用 ::slotted() 添加样式。

此外,子元素可以从 shadow 树外部添加样式,因此你应该将 ::slotted() 样式视为可以被覆盖的默认样式。

**ShadyCSS polyfill 在插槽内容方面的限制。**有关如何以兼容 polyfill 的方式使用 ::slotted() 语法的详细信息,请参见 ShadyCSS 限制

在模板中定义限定作用域的样式

Permalink to "在模板中定义限定作用域的样式"

我们建议使用静态 styles 类字段以获得最佳性能。但是,有时你可能想要在 Lit 模板中定义样式。有两种方法可以在模板中添加限定作用域的样式:

这些技术各有优缺点。

通常,样式放在静态 styles 类字段中;但是,元素的静态 styles每个类评估一次。有时,你可能需要每个实例自定义样式。对于这种情况,我们建议使用 CSS 属性来创建可主题化的元素。或者,你也可以在 Lit 模板中包含 <style> 元素。这些会每个实例更新。

**ShadyCSS polyfill 在每个实例样式方面的限制。**使用 ShadyCSS polyfill 不支持每个实例的样式。有关详细信息,请参见 ShadyCSS 限制

在 style 元素内使用表达式有一些重要的限制和性能问题。

**ShadyCSS polyfill 在表达式方面的限制。**由于 ShadyCSS polyfill 的限制,<style> 元素中的表达式在 ShadyCSS 中不会每个实例更新。此外,使用 ShadyCSS polyfill 时,<style> 节点可能不能作为表达式值传递。有关更多信息,请参见 ShadyCSS 限制

<style> 元素内评估表达式的效率极低。当 <style> 元素内的任何文本发生变化时,浏览器必须重新解析整个 <style> 元素,导致不必要的工作。

为了减轻这种成本,请将需要每个实例评估的样式与不需要的样式分开。

导入外部样式表(不推荐)

Permalink to "导入外部样式表(不推荐)"

虽然你可以在模板中使用 <link> 包含外部样式表,但我们不推荐这种方法。相反,样式应该放在静态 styles 类字段中。

外部样式表注意事项。

  • ShadyCSS polyfill 不支持外部样式表。
  • 外部样式在加载时可能会导致未样式化内容闪烁(FOUC)。
  • href 属性中的 URL 是相对于主文档的。如果你正在构建应用程序并且你的资源 URL 是已知的,这没问题,但在构建可重用元素时避免使用外部样式表。

使样式动态化的一种方法是在模板中的 classstyle 属性中添加表达式。

Lit 提供了两个指令,classMapstyleMap,以方便在 HTML 模板中应用类和样式。

有关这些和其他指令的更多信息,请参见内置指令的文档。

要使用 styleMap 和/或 classMap

  1. 导入 classMap 和/或 styleMap

  2. 在你的元素模板中使用 classMap 和/或 styleMap

有关更多信息,请参见 classMapstyleMap

通过一起使用 CSS 继承CSS 变量和自定义属性,可以轻松创建可主题化的元素。通过应用 CSS 选择器来自定义 CSS 自定义属性,基于树的和每个实例的主题化都很容易应用。这里有一个例子:

CSS 继承允许父元素和宿主元素将某些 CSS 属性传播给它们的后代。

并非所有 CSS 属性都继承。继承的 CSS 属性包括:

  • color
  • font-family 和其他 font-* 属性
  • 所有 CSS 自定义属性(--*

有关更多信息,请参见 MDN 上的 CSS 继承

你可以使用 CSS 继承在祖先元素上设置样式,这些样式会被其后代继承:

所有 CSS 自定义属性(--custom-property-name)都会继承。你可以使用这个特性使你的组件的样式可以从外部配置。

以下组件将其背景色设置为一个 CSS 变量。如果 DOM 树中的祖先选择器设置了 --my-background 的值,CSS 变量就使用该值,否则默认为 yellow

这个组件的用户可以使用 my-element 标签作为 CSS 选择器来设置 --my-background 的值:

--my-background 可以为每个 my-element 实例配置:

有关更多信息,请参见 MDN 上的 CSS 自定义属性