# 有作用域的 CSS

<style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。这类似于 Shadow DOM 中的样式封装。它有一些注意事项,但不需要任何 polyfill。它通过使用 PostCSS 来实现以下转换:

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

转换结果:

<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

# 注意


# 混用本地和全局样式

你可以在一个组件中同时使用有作用域和无作用域的样式:

<style>
/* 全局样式 */
</style>

<style scoped>
/* 本地样式 */
</style>

# 子组件的根元素

使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件有作用域的 CSS 和子组件有作用域的 CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。

# 深度作用选择器

你很可能会遇到的问题

vue组件编译后,会将 template 中的每个元素加入 [data-v-xxxx] 属性来确保 style scoped 仅本组件的元素而不会污染全局,但如果你引用了第三方组件

默认只会对组件的最外层(div)加入这个 [data-v-xxxx] 属性,但第二层开始就没有效果了。 如下所示: 第一层还有 data-v-17bb9a05, 但第二层的 .ui-cells 就没有了。

<div data-v-17bb9a05 class="level1">
  <!---->
  <div class="ui-cells">

所以,如果你期待通过如下方式修改 ui-cells 的样式。是没有任何效果的:

<style scoped>
    .level1 .ui-cells {
        // ...
    }
</style>

这是因为,所有的scoped中的css最终编译出来都会变成这样:

.level1[data-v-17bb9a05] .ui-cells[data-v-17bb9a05]

解决方法一:除非你将 scoped 移除,或者新建一个没有 scoped 的 style(一个.vue文件允许多个style)
解决方法二:深度作用选择器 >>> (注意,只作用于css)

.level1 >>> .ui-cells {
    // ...
}

但如果是sass/less的话可能无法识别,这时候需要使用 /deep/ 选择器。


如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:

<style scoped>
.a >>> .b { /* ... */ }
</style>

上述代码将会编译成:

.a[data-v-f3f3eg9] .b { /* ... */ }

有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 操作符取而代之——这是一个 >>> 的别名,同样可以正常工作。

ex: bootstrap-vue form-select change border

<style lang="scss" scoped>
.form-group /deep/ .custom-select {
  border: 1px solid #fff;
}
</style>