Skip to content

Возможности CSS в однофайловых компонентах

CSS с ограниченной областью действия

Когда секция <style> имеет атрибут scoped, его CSS будет применяться только к элементам текущего компонента. Это похоже на инкапсуляцию стилей в Shadow DOM. Есть некоторые оговорки, но зато не требуется никаких полифилов. Это достигается путем использования PostCSS для преобразования следующего кода:

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

<template>
  <div class="example">привет</div>
</template>

В этот код:

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

<template>
  <div class="example" data-v-f3f3eg9>привет</div>
</template>

Корневые элементы дочернего компонента

При использовании scoped стили родительского компонента не будут проникать в дочерние компоненты. Однако корневой элемент дочернего компонента будет подвержен влиянию как родительского, так и дочернего CSS. Это сделано специально для того, чтобы родитель мог стилизовать корневой элемент дочернего компонента в целях вёрстки.

Глубокие селекторы

Если требуется, чтобы селектор в scoped стилях был "глубоким", т.е. влиял на дочерние компоненты, можно использовать псевдокласс :deep():

vue
<style scoped>
.a :deep(.b) {
  /* ... */
}
</style>

Код выше будет скомпилирован в:

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

Совет

Содержимое DOM, созданное при помощи v-html, не подвержено влиянию стилей c ограниченной областью действия, но его все же можно стилизовать с помощью глубоких селекторов.

Селекторы слотов

По умолчанию стили с ограниченной областью действия не влияют на содержимое, отображаемое с помощью <slot/>, так как считается, что оно принадлежит родительскому компоненту, который его передаёт. Чтобы явно указать на содержимое слота, используйте псевдокласс :slotted:

vue
<style scoped>
:slotted(div) {
  color: red;
}
</style>

Глобальные селекторы

Если необходимо, чтобы одно правило применялось глобально, можно использовать псевдокласс :global, а не создавать еще одну секцию <style> (см. ниже):

vue
<style scoped>
:global(.red) {
  color: red;
}
</style>

Сочетание локальных и глобальных стилей

В одном компоненте можно вместе использовать как scoped, так и обычные секции style:

vue
<style>
/* глобальные стили */
</style>

<style scoped>
/* локальные стили */
</style>

Советы по использованию стилей с ограниченной областью действия

  • Стили с ограниченной областью действия не избавляют от необходимости использования классов. Ввиду того, как браузеры отрисовывают различные CSS-селекторы, p { color: red } будет работать гораздо медленнее при использовании стилей с ограниченной областью действия (т.е. в сочетании с селектором атрибутов). Если вместо этого использовать классы или идентификаторы, как, например, в .example { color: red }, то это практически исключает снижение производительности.

  • Будьте осторожны с селекторами потомков в рекурсивных компонентах! Для правила CSS с селектором .a .b, если элемент, соответствующий .a, содержит рекурсивный дочерний компонент, то все .b в этом дочернем компоненте будут соответствовать правилу.

CSS модули

Секция <style module> компилируется как CSS модуль и объявляет результирующие CSS-классы компоненту в виде объекта под ключом $style:

vue
<template>
  <p :class="$style.red">Это должно быть красным</p>
</template>

<style module>
.red {
  color: red;
}
</style>

Полученные классы хэшируются во избежание коллизий, что позволяет добиться того же эффекта, что и при выборе CSS с ограниченной областью действия только для текущего компонента.

Обратитесь к спецификации CSS модулей для получения более подробной информации, такой как глобальные исключения и композиция.

Внедрение пользовательского имени

Можно настроить ключ свойства объекта внедряемых классов, указав значение атрибуту module:

vue
<template>
  <p :class="classes.red">red</p>
</template>

<style module="classes">
.red {
  color: red;
}
</style>

Использование с Composition API

Доступ к внедряемым классам можно получить в setup() и <script setup> через API useCssModule. Для секций <style module> с пользовательским внедряемым именем, useCssModule принимает в качестве первого аргумента соответствующее значение атрибута module:

js
import { useCssModule } from 'vue'

// внутри области видимости setup()...
// по умолчанию, возвращает классы для <style module>
useCssModule()

// при указании имени,  возвращает классы для <style module="classes">
useCssModule('classes')
  • Example
vue
<script setup lang="ts">
import { useCssModule } from 'vue'

const classes = useCssModule()
</script>

<template>
  <p :class="classes.red">red</p>
</template>

<style module>
.red {
  color: red;
}
</style>

v-bind() внутри CSS

Однофайловые компоненты в секциях <style> поддерживают привязку значений CSS к динамическому состоянию компонента через CSS-функцию v-bind:

vue
<template>
  <div class="text">привет</div>
</template>

<script>
export default {
  data() {
    return {
      color: 'red'
    }
  }
}
</script>

<style>
.text {
  color: v-bind(color);
}
</style>

Синтаксис работает с <script setup> и поддерживает JavaScript выражения(должны быть обёрнуты в кавычки):

vue
<script setup>
import { ref } from 'vue'
const theme = ref({
    color: 'red',
})
</script>

<template>
  <p>привет</p>
</template>

<style scoped>
p {
  color: v-bind('theme.color');
}
</style>

Фактическое значение будет скомпилировано в хэшированное пользовательское свойство CSS, поэтому CSS остаётся статичным. Пользовательское свойство будет применяться к корневому элементу компонента с помощью inline-стилей и реактивно обновляться при изменении исходного значения.

Возможности CSS в однофайловых компонентахУже загружено