Компонент: стили

В статье о шаблоне мы упоминали возможность применения динамических атрибутов class и style, передавая в них JavaScript-выражения. Здесь мы подробнее разберём работу с этими атрибутами, а также рассмотрим блок style внутри компонента.

В шаблоне допускается одновременное использование статических и динамических классов и стилей:

<a
        class="link"
        :class="dynamicClass"
        style="color: blue;"
        :style="dynamicStyle"
        href="/"
>
    Link text
</a>

Такая запись полностью корректна. К ссылке будут применены как динамические, так и статические классы и стили.

Динамические class и style принимают массивы и объекты. Рассмотрим примеры.

С использованием массивов:

<a
  class="link"
  :class="[myClass1, myClass2, myClass3]"
  style="color: blue;"
  :style="[myStyle1, myStyle2, myStyle3]"
  href="/"
>
  Link text
</a>

Каждый из этих классов может быть параметром компонента, свойством, вычисляемым свойством или методом (в последнем случае его необходимо вызывать с круглыми скобками).

С использованием объектов:

<a
  class="link"
  :class="{ active: isActive, visited: isVisited, 'admin-class': userRole === 'admin'  }"
  style="color: blue;"
  :style="{ color: computedColor }"
  href="/"
>
  Link text
</a>

Смешанный вариант. Объекты в массиве:

<a
  class="link"
  :class="[{ active: isActive }, myClass1, myClass2]"
  style="color: blue;"
  :style="[{ color: computedColor }, myStyle1, myStyle2]"
  href="/"
>
  Link text
</a>

Это позволяет выстраивать сложные условия назначения классов и стилей, делая стилизацию компонента по-настоящему динамической.

Блок стилей в компоненте

Мы разобрали различные способы работы с классами и стилями в шаблоне. Теперь перейдём к блоку стилей в компоненте. В простейшем виде это обычный блок:

<style>
.some-class {
  display: flex;
  justify-content: center;
  ...
}
</style>

Таких блоков в компоненте может быть несколько. К примеру, в одном блоке располагаются основные стили, а во втором — классы, связанные с анимацией. Это зачастую удобно.

Тег <style> поддерживает атрибуты scoped и module, которые служат для ограничения области видимости стилей.

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

<template>
  <div class="some-class">...</div>
</template>

<style scoped>
.some-class {
  display: flex;
  justify-content: center;
  ...
}
</style>

При компиляции будет сгенерирован уникальный дата-атрибут, применяемый при назначении стилей. Это обеспечивается за счёт PostCSS. Результат будет выглядеть следующим образом:

<template>
  <div class="some-class" data-v-f3f3eg9 >...</div>
</template>

<style>
.some-class[data-v-f3f3eg9] {
  display: flex;
  justify-content: center;
  ...
}
</style>

Допускается наличие блоков style как с атрибутом scoped, так и без него в рамках одного компонента.

В проектах мы будем применять scoped-стили. Для ограничения видимости стилей также можно использовать CSS-модули. Подробнее о них можно узнать по ссылке.

Благодаря scoped стили родительского компонента не затрагивают содержимое дочерних компонентов. Тем не менее иногда бывает необходимо задать определённые стили для дочернего компонента из родительского — для этого применяются глубокие селекторы.

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

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

<template>
  <div class="parent">
    <child-component />
  </div>
</template>

<style scoped>
.parent :deep(.some-class) {
  display: flex;
  justify-content: center;
  ...
}
</style>

Таким образом вы получите доступ к классу .some-class дочернего компонента и рекурсивно ко всем его вложенным дочерним компонентам.

Стили с ограниченной областью

По умолчанию CSS-стили не распространяются на контент, размещённый в слотах (slots). Чтобы изменить это поведение, используется атрибут :slotted.

<style scoped>
:slotted(.some-class) {
  display: flex;
  justify-content: center;
  ...
}

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

Иногда требуется применить CSS-свойства на глобальном уровне. Для этого можно воспользоваться атрибутом global.

<style scoped>
:global(.some-class) {
  display: flex;
  justify-content: center;
  ...
}

Использование локальных и глобальных стилей в одном компоненте

Vue допускает наличие двух блоков стилей в одном компоненте — для локальных и глобальных правил.

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

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

Атрибут lang

Тег style поддерживает атрибут lang. По умолчанию используется CSS, но можно подключить и препроцессор:

<template>
  <div class="some-class">...</div>
</template>

<style scoped lang="stylus">
.some-class
  display flex
  justify-content center
...
</style>

В данном примере используется Stylus. Помимо него, вы можете применять такие препроцессоры, как Sass, SCSS, LESS.

В наших проектах мы используем SCSS.

Использование стилей в учебном проекте

В учебном проекте общие стили расположены в директории src/assets/scss.

В корневом компоненте App.vue рекомендуется импортировать файл src/assets/scss/app.scss, содержащий глобальные стили приложения.

В компонентах нередко потребуется импортировать два файла:

  • src/assets/scss/ds-system/ds.scss — правила дизайн-системы: типографика и цвета;
  • src/assets/scss/mixins/mixins.scss — набор примесей (миксинов), преимущественно для позиционирования элементов.

Предполагается, что вы уже знакомы с основами работы с Sass/SCSS. Если нет, изучите руководство.

Проверьте себя

1.Что делает атрибут scoped в теге <style> компонента Vue?

2.Какие способы передачи динамических классов в шаблоне Vue корректны?

Несколько вариантов

3.Какой псевдокласс используется для проникновения scoped-стилей в дочерние компоненты?