跳转到内容

5. CSS 作用域(CSS Scoping)

.sharq<style> 块是 SFC 的一部分(与 <template><script> 同处一个文件)。 有两种模式:global(默认)和 scoped

全局 <style>(默认,推荐)

不加 scoped 属性时,CSS 会原样(raw)输出到组件生成的 USS 中。选择器会匹配组件子树中任意位置的 同名 class,因此BEM 命名本身就已经起到隔离作用

xml
<style>
.card { flex-grow: 1; background-color: #1f1f1f; }
.card__title { font-size: 18px; color: white; }
.card__title:hover { opacity: 0.8; }
</style>
css
/* Compiled Card.g.uss — identical, no rewriting: */
.card { flex-grow: 1; background-color: #1f1f1f; }
.card__title { font-size: 18px; color: white; }
.card__title:hover { opacity: 0.8; }

根规则(.card)和子规则(.card__title)都能匹配,因为元素带有这些 class(来自模板中的 class="…")。这是可靠的默认方式——建议优先使用,并搭配唯一的 BEM class 名(component__part) 来实现隔离。

Scoped <style scoped>

带上 scoped 后,编译器会给每一条选择器追加一个组件专属的作用域 class .s-{hash}, 并只把这个作用域 class 加到组件根元素上(生成的 Build() 中的 ApplyScopedAttributeAddToClassList("s-xxxxxx")):

xml
<style scoped>
.card { flex-grow: 1; }
.card:hover { opacity: 0.9; }
</style>
css
/* Compiled Card_scoped.g.uss: */
.card.s-a1b2c3 { flex-grow: 1; }
.card.s-a1b2c3:hover { opacity: 0.9; }

因为作用域 class 落在根元素上,所以 .card.s-a1b2c3 能正确匹配到根元素。

重要限制。 只有元素会获得 .s-{hash}——子元素不会。 因此像 .card__title 这样的 scoped 子级选择器会变成 .card__title.s-a1b2c3, 这要求两个 class 出现在同一个元素上,所以不会匹配到子元素。scoped 样式请只用于 根/宿主级规则。要给子元素设置样式,请使用带 BEM class 名的全局 <style>(它能可靠地 匹配到子元素)。

配套的 unscoped USS(备用方案)

对于两种模式都无法表达的规则——例如从组件外部进行定位,或是主题级的 :root 变量—— 可以在组件旁放一个不带作用域的 USS 文件(Resources/SusRuntime/Card.uss);它会在运行时通过 LoadCompanionStyleSheets() 自动加载。

生成的文件名

来源生成的 USS
全局 <style>Component.g.uss
<style scoped>Component_scoped.g.uss
模板元素上的内联 style="…"Component_static.g.uss

另见 .sharq 格式 的 Style 一节。