样式组件
Shadow DOM
什么是 Shadow DOM
Shadow DOM 是一种内置于浏览器中的 API,允许进行 DOM 封装和样式封装。 Shadow DOM 将我们的组件与周围环境隔离开来。这意味着我们不需要担心我们的 CSS 的范围是否正确,也不需要担心我们的内部 DOM 会被我们组件之外的任何东西干扰。
浏览器支持
Shadow DOM 在下列浏览器中原生支持:
- Chrome
- Firefox
- Safari
- Opera
在不支持 Shadow DOM 的浏览器中,我们回退到 scoped-CSS。这为您提供了随 Shadow DOM 一起提供的样式封装,但无需加载巨大的 Shadow DOM polyfill。
对什么是作用域 CSS 感到困惑?别担心,我们会稍后解释 详细说明。
在 Stencil 中的 Shadow DOM
Shadow DOM is not currently turned on by default for web components built with Stencil. To turn on Shadow DOM in a web component built with Stencil, you can use the
shadow
param in the component decorator. Below is an example of this:
对于使用 Stencil 构建的 Web 组件,Shadow DOM 默认未打开。如果需要打开,配置组件装饰器中的 shadow
参数。下面是一个例子:
@Component({
tag: 'shadow-component',
styleUrl: 'shadow-component.css',
shadow: true
})
export class ShadowComponent {
}
Shadow DOM 的注意事项
QuerySelector:当使用 Shadow DOM 并且您想查询 Web 组件内的元素时,您必须使用
this.el.shadowRoot.querySelector()
。因为 Web 组件中的所有 DOM 都在 Shadow DOM 创建的 shadowRoot 中。全局样式:要使用 Shadow DOM 对组件进行外部样式设置,您必须使用 CSS 自定义属性 或建议的 [CSS Shadow Parts ](https://meowni.ca/posts/part-theme-explainer/)。
通常,您会将样式包装在组件的标签名称中,如下所示:
my-element {
color: black;
}
my-element div {
background: blue;
}
启用 Shadow DOM 后,shadow root 中的元素是有作用域的,并且组件外部的样式不适用。因此,组件内的 CSS 选择器可以被简化,上面的例子可以是:
:host {
color: black;
}
div {
background: blue;
}
作用域 CSS
在当前不支持 Shadow DOM 的浏览器中,使用 Stencil 构建的 Web 组件将回退到使用作用域 CSS 而不是加载体积较大的 Shadow DOM polyfill。 Scoped CSS 通过在运行时为每个样式附加一个 data 属性来自动将 CSS 范围限定。
全局样式
虽然 Stencil 鼓励开发人员编写适用于每个组件的样式,但有时需要具有适用于整个文档的全局样式,而不管使用哪些组件。
为此,stencil.config.ts
带有一个可选的
globalStyle
设置,它指向一个样式表路径。
export const config: Config = {
namespace: 'app',
globalStyle: 'src/global/global.css',
outputTarget: [{
type: 'www'
}]
}
编译器将在 global.css
上运行相同的压缩、自动前缀和插件,并为
www
和 [dist
](https ://stenciljs.com/docs/distribution) 输出目标。生成的文件将始终具有
.css
扩展名并被命名为指定的
namespace
。
在上面的例子中,由于命名空间是app
,生成的全局样式文件将位于:./www/build/app.css
。
这个文件必须 手动导入 到你的应用程序的
index.html
中,你可以在src/index.html
中找到它:
<link rel="stylesheet" href="/build/app.css">
请记住,应该为 global 样式保留全局样式,即,您应该尽量避免使用它来设置组件的样式,相反,一些有趣的用例可以是:
- 主题:定义跨应用程序使用的 CSS 变量
- 使用
@font-face
加载字体 - 应用广泛的字体系列
- 样式正文背景
- CSS 重置
CSS 变量
什么是 CSS 变量?
CSS 变量 很像 [Sass 变量](https://ionicframework.com/docs/theming/sass- variables/),但内置于浏览器中。 CSS 变量允许您指定可在您的应用程序中使用的 CSS 属性。
用例
CSS 变量的一个用例是颜色。如果您的应用程序有一个主要品牌颜色在您的应用程序中使用,那么您可以为它创建一个变量,然后在应用程序中需要该颜色的任何地方使用该变量,而不是在应用程序中的每个地方都使用相同的颜色.此外,如果您需要更改此颜色,您只需更改变量,然后它就会在您的应用程序中更新。
在 Stencil 中使用 CSS 变量
以下是在 Stencil 中使用 CSS 变量的推荐步骤:
- 创建一个 CSS 文件来保存您的变量定义。我们通常建议在
src/global/
中创建一个variables.css
文件 - 然后你可以把这个配置
globalStyle: 'src/global/variables.css'
放到你的stencil.config.ts
文件中。
在此之后!就可以可以开始定义变量了。
定义 CSS Variables
这是定义 CSS 变量的示例:
/* 在我们的文件 src/global/variables.css file 中 */
:root {
--app-primary-color: #488aff;
}
在这个例子中,我们定义了一个名为 --app-primary-color
的 CSS 变量,它被设置为颜色
#488aff
。这个例子中的 :root
选择器是一个 CSS 伪类,它定义了您的项目(通常是 <html>
),以便该变量可以在您的应用程序中使用。
使用 CSS 变量
这是使用我们上面定义的 CSS 变量的示例:
h1 {
color: var(--app-primary-color)
}
这会将我们在 CSS 变量中定义的颜色(在本例中为 #488aff
)应用到我们的
h1
元素。
IE 兼容性
IE11 本身不支持 CSS 变量,但是 stencil 确实提供了 polyfill,然而 JS 不可能 polyfill CSS 功能。
对于原生支持它的浏览器,CSS 变量的模板 polyfill 有很多限制,并且会产生大量的性能开销。
- 全局 CSS 变量只能在
:root
或html
中声明,它们不能是动态的。 - 只有
shadow
或scoped
组件的样式表可以有动态 CSS 变量。 - 组件中的 CSS 变量只能在
:host(...)
选择器中定义。
:host() {
/* This works */
--color: black;
}
:host(.white) {
/* This works */
--color: white;
}
.selector {
/* This DOES NOT work in IE11 */
--color: red;
}
- 组件中的 CSS 变量可以在任何选择器中使用 (
var(--thing)
)。
在 IE11 中使用 CSS 变量的性能开销在 CPU 时间和内存方面有所提升。这是因为为了“模拟”CSS 变量的动态特性,polyfill 需要动态生成不同的样式表 PER 实例。例如,如果 DOM 中有 200 个
my-cmp
元素,polyfill 将附加 200 个类似的 <style>
标签来为每个元素设置样式。
IE11 处理的样式表总量会快速增长,消耗大量内存,并且每次样式失效都需要大量 CPU。
Contributors
Thanks for your interest!
We just need some basic information so we can send the guide your way.