Отказ от scoped стилей в Vue
При работе с Vue многие привычно используют <style scoped>, ограничивая стили текущим компонентом. Разберёмся, действительно ли это нужно, или стало устаревшей привычкой, от которой можно отказаться.
scoped в Vue
<style scoped> добавляет каждому селектору уникальный атрибут вроде data-v-xxxx.
<template>
<button class="button">
Click
</button>
</template>
<style scoped>
.button { color: red; }
</style>Компилируется в:
.button[data-v-1234] { color: red; }- Плюсы: полная изоляция стилей, отсутствие коллизий. Такие стили легко переносить между проектами и вы не рискуете случайно задеть существующие.
- Минусы: небольшой runtime/compile overhead, раздувание CSS из-за добавленных хешей.
Scoped удобен для быстрых прототипов, но для крупных проектов это чаще лишняя нагрузка.
module в Vue
Vue поддерживает ещё один способ изоляции — CSS Modules, через <style module>.
<template>
<button :class="$style.button">
Click
</button>
</template>
<style module>
.button { color: red; }
</style>Классы получают уникальные имена при компиляции (например button_abc123) и доступ через объект $style.
- Плюсы: полная изоляция, удобно для динамических классов, можно комбинировать с BEM.
- Минусы: синтаксис чуть сложнее (
$styleвместо обычного класса), больше boilerplate, не так нагляден для людей привыкших к plain CSS.
Если BEM уже соблюдается, CSS Modules чаще всего не нужны, но для компонентов с динамическими классами могут быть полезны.
Уникальные имена классов (BEM)
Если проект использует строгий нейминг, например BEM (Block-Element-Modifier), scoped можно не применять. Классы блоков уже уникальные, а дочерние элементы и модификаторы ограничены областью блока:
<style>
.block {
display: flex;
flex-direction: column;
&__element {
flex-basis: 50%;
}
&--modifier {
flex-direction: row;
}
}
</style>- Плюсы: plain CSS без
data-v-xxxx, уменьшенный размер бандла, отсутствие runtime/compile overhead. Отсутствие коллизий при строгом следовании BEM. - Минусы: требуется соблюдать BEM нейминг, который не всем по вкусу, незначительное увеличение времени на code review.
Этот вариант подходит для команд с code review и зафиксированными стандартами разработки.
Валидация классов и стилей
Соблюдение этих правил можно автоматизировать с помощью линтеров.
- Stylelint — запрет не-BEM классов:
{
"selector-class-pattern": "[a-z]([a-z-]+)?(__([a-z]+-?)+)?(--([a-z]+-?)+){0,2}"
}- Eslint — запрет
scopedв<style>Vue-компонентов:
{
"vue/enforce-style-attribute": ["error", { "allow": ["plain"] }]
}Заключение
- Scoped стилей можно смело избегать, если применяется строгий BEM.
- CSS без
scopedуменьшает размер бандла и нагрузку на runtime. - Линтеры
stylelintиeslintпомогут ускорить миграцию и предотвратить ошибки в будущем. - Scoped остаётся безопасным и допустимым подходом, но только если понимать цену его использования.
