Возможности 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-стилей и реактивно обновляться при изменении исходного значения.