От автора: компоненты Angular имеют это интересное поведение, называемое ViewEncapsulation — оно определяет стиль для компонента, и область его применения ограничивается только этим конкретным компонентом. В зависимости от его настройки, переопределение этих стилей, однако, может быть сложным. Как же тогда мы можем иначе добавлять стили в Angular приложениям?
Проблема
Предположим, что у вас есть TrexComponent и его стили определяются в файле trex.component.scss. Благодаря ViewEncapsulation.Emulated (который установлен по умолчанию) эти стили не будут влиять на любую другую часть вашего приложения.
Но это работает и наоборот: если, скажем, ваш корневой AppComponent определяет некоторые стили, они не будут применяться к дочерним компонентам.
С помощью ViewEncapsulation.Emulated
стили, определенные в компоненте предка, не влияют на компонент-потомок.
Вы можете установить глобальные стили в файле глобальных стилей (обычно src/styles.scss), а затем они задаются для всех компонентов в приложении, и, что более важно, вы не можете делать это динамически, например, когда пользователи выполняют некоторые настройки и хотят изменить стиль, основываясь на этом.
Глобально установленные стили влияют на компоненты… но их трудно изменить динамически.
Эта проблема влияния на стили компонента еще более очевидна в случае установки Native (теперь устаревшей) или инкапсуляции ShadowDom. Поскольку компонент «скрыт» за Shadow Root, даже глобальные стили не будут влиять на него.
Даже если вы не используете ViewEncapsulation.ShadowDom в своем обычном приложении, это необходимо, если вы хотите создать повторно используемый веб-компонент — так что это действительно проблема, которую нам нужно научиться решать.
С помощью ViewEncapsulation.Emulated
, глобальные стили также не влияют на компонент-потомок.
Решение
Чтобы справиться с этим, мы будем использовать пользовательские свойства CSS, также известные, как переменные CSS.
Имена свойств, которые имеют префикс «—», например, «—example-name», представляют собой пользовательские свойства, содержащие значение, которое может использоваться в других объявлениях с помощью функции var().
Это означает, что вы определяете пользовательское свойство так же, как и обычное свойство css, например. «font-size: 16px», и на него можно ссылаться в любом месте каскада (во всем поддереве элемента, соответствующем селектору, который вы использовали при определении свойства.)
Теперь, если вы не работали с пользовательскими свойствами css, прежде всего вам потребуется какое-то время, чтобы погрузиться в эту тему (говорю по опыту…), но это чрезвычайно мощный инструмент. Важно не думать о них как об альтернативе переменных SASS, или Less — они вычисляются только во время компиляции, поэтому они статичны. Вместо этого рассматривайте их так же, как и любое другое свойство CSS (например, font-size). Таким образом, вы можете, например:
устанавливать разные значения для разных компонентов («GreenDinosComponent» вместо «PinkDinosComponent»),
изменять их с помощью псевдо-классов (:hover {—main-color: darkgreen})
… или медиа-запросов
и, наконец, устанавливать их динамически с помощью специальной директивы!
Простой директивы, такой как приведенная ниже, должно быть достаточно.
См. источник: https://gist.github.com/sulco/6860711bd1f7d72344f317118a28ff4f
Следует отметить, что тип привязок [ngStyle]=»{….}» не будет работать сейчас, — см. обсуждение этой проблемы на Github — поэтому пользовательская директива, подобная этой, является одним из возможных обходных путей.
Демо-приложение
Итак, я показал вам несколько иллюстраций, некоторые фрагменты кода, но как собрать это вместе? Действительно ли это работает? Ну, убедитесь сами:
Вы можете поэкспериментировать с приложением здесь
Смотрите исходный код на Github
Стоит отметить:
У всех динозавров есть по умолчанию ViewEncapsulation.Emulated, за исключением T-Rex, который использует ViewEncapsulation.ShadowDom — так что вы можете увидеть, что темизация работает в обоих случаях.
Фактически вам не нужно добавлять пользовательские свойства [dtTheme] непосредственно к компоненту, их можно применять к любому элементу HTML в вашем приложении. Тема будет применяться ко всему внутри:
<div [dtTheme]="getCustomTheme()"> <dt-ptero></dt-ptero> <dt-trex></dt-trex> </div>
Я использую как пользовательские свойства CSS, так и переменные SASS. Да, ничто не мешает вам использовать оба, на самом деле это часто имеет смысл (см. cследующий раздел «Эпилог»)
Пользовательские свойства поддерживаются во всех существующих браузерах (кроме IE, см. таблицу совместимости).
Эпилог
Итак, теперь, когда мы рассмотрели отличный случай использования пользовательских свойств, вы можете задаться вопросом: нужны ли нам еще такие вещи, как переменные SASS? И если ответ «да», то когда использовать какой способ хранения значений CSS? Общий ответ:
используйте SASS / Less, когда вам нужно статически устанавливать значения, когда вам нужно выполнить некоторые операции (например, `$color2 = lighten($mycolor)) во время компиляции приложения. Используйте их для настройки ваших общих CSS-структур. Чтобы настроить Bootstrap / Foundation / и т. д. под свои потребности.
используйте пользовательские свойства, когда вам нужно динамически изменять значения, например, иметь бесконечное количество цветовых комбинации возможности настроек пользователями. Используйте их, когда вам нужна возможность темизациии для компонентов
Автор: Tomek Sułkowski
Источник: https://medium.com/
Редакция: Команда webformyself.