Vue.js предоставляет мощный механизм для создания компонентов с инкапсулированной структурой и стилями. Одной из ключевых особенностей является возможность использования scoped стилей, позволяющих применять CSS только к текущему компоненту без риска затрагивания глобальных элементов страницы или других компонентов.
В компонентах Vue стили объявляются внутри <style>
с атрибутом scoped:
<template>
<div class="card">
<h2 class="title">Заголовок</h2>
<p class="description">Описание компонента</p>
</div>
</template>
<script>
export default {
name: 'CardComponent'
};
</script>
<style scoped>
.card {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
}
.title {
font-size: 18px;
color: #333;
}
.description {
font-size: 14px;
color: #666;
}
</style>
При использовании scoped Vue автоматически добавляет
уникальные атрибуты к элементам DOM компонента и к соответствующим
селекторам CSS. Например, <div class="card"> может
получить атрибут data-v-123abc, а CSS будет сгенерирован
как .card[data-v-123abc], что исключает влияние на другие
компоненты.
Scoped стили работают за счет компиляции CSS с атрибутами:
Пример с вложенными элементами:
<template>
<div class="menu">
<ul>
<li>Пункт 1</li>
<li>Пункт 2</li>
</ul>
</div>
</template>
<style scoped>
.menu ul {
list-style: none;
padding: 0;
}
.menu li {
padding: 8px 0;
}
</style>
Каждый селектор .menu ul и .menu li будет
сгенерирован с уникальным атрибутом, исключая конфликты с глобальными
<ul> и <li>.
В некоторых случаях требуется смешивание scoped и глобальных правил.
Для этого используется селектор ::v-deep или глобальный
<style> без scoped.
Пример использования ::v-deep:
<template>
<div class="container">
<button class="btn">Нажми меня</button>
</div>
</template>
<style scoped>
.container ::v-deep(.btn) {
background-color: blue;
color: white;
}
</style>
Селектор ::v-deep позволяет стилизовать глубоко
вложенные компоненты или сторонние классы, игнорируя локальную
изоляцию.
scoped не
изолирует селекторы от глобальных тегов напрямую. Например, селектор
body будет глобальным, даже если указан
scoped.::v-deep или глобальные селекторы.scoped добавляет
атрибуты к DOM, но современный рендеринг Vue делает это почти незаметным
по производительности.Scoped стили отлично сочетаются с препроцессорами CSS, такими как
SASS, LESS, Stylus. Атрибут scoped
работает независимо от препроцессора.
<style lang="scss" scoped>
.card {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
.title {
font-size: 18px;
color: #333;
}
.description {
font-size: 14px;
color: #666;
}
}
</style>
Синтаксис вложенных селекторов упрощает структуру и повышает читаемость кода.
Scoped стили также прекрасно работают с динамическими
классами через директиву :class:
<template>
<div :class="['alert', type]">Сообщение</div>
</template>
<script>
export default {
data() {
return {
type: 'success' // success, warning, error
};
}
};
</script>
<style scoped>
.alert {
padding: 12px;
border-radius: 4px;
}
.success {
background-color: #dff0d8;
color: #3c763d;
}
.warning {
background-color: #fcf8e3;
color: #8a6d3b;
}
.error {
background-color: #f2dede;
color: #a94442;
}
</style>
Vue автоматически связывает динамические классы с уникальными атрибутами scoped, что гарантирует локальность стилей для всех состояний.
Scoped стили являются мощным инструментом для создания изолированных и предсказуемых компонентных интерфейсов, позволяя управлять CSS на уровне отдельных компонентов без риска глобальных конфликтов и сохраняя полную гибкость с препроцессорами и динамическими классами.