При разработке интерфейсов часто возникает необходимость динамически менять стили HTML-элементов в зависимости от текущего состояния приложения. Существует довольно много способов передать данные из Javascript в CSS и в этой статье я предлагаю их рассмотреть.
Самый простой способ стилизовать элемент — указать CSS-свойства прямо в HTML:
Этот древнейший споособ стилизации максимально прост в использовании, но имеет ряд существенных недостатков:
Смешивается структура страницы и её оформление (мы же не пишем Javascript прямо в HTML);
Нет возможности использовать каскад, медиа-выражения и некоторые другие инструменты, доступные в CSS;
Нет возможности переиспользовать стили для одинаковых элементов.
В JSX последний пункт можно решить с помощью создания переменной:
Похожий подход применяется в React Native , но там каскада нет и возможности CSS довольно сильно ограничены, а в бразуере — родной среде для CSS — подобных ограничений нет и было бы неразумно отказываться от такой богатой функциональности.
Проблема выше решается путём выноса стилей из HTML:
Придумывая название класса, мы создаём некую абстракцию, которую зачастую наделяем смыслом. Вероятно этот класс будет представлять собой некий компонент, но у компонентов в привычном нам понимании бывают свойства, которые можно менять при необходиости. И это не CSS свойства — мы создали абстракцию в виде класса над стилями, не будем спешить её ломать, смешивая её с конкретными стилевыми параметрами.
Раз речь зашла о компонентах, попробуем вернуться к React и посмотреть, как подобная задача решается там.
В общем-то очень остроумно проблему решают CSS-in-JS фреймворки: чтобы не передавать данные из JS в CSS, мы перенесли CSS в JS:
Если нам понадобится передать данные из JS в CSS, мы можем сделать это так же, как и с любым другим React-компонентом:
Мы передаём некий дискретный набор данных в компонент и для каждой новой их комбинации styled-components будет создавать уникальный класс и вставлять его в DOM. Но что, если параметр не дискретный и меняется часто?
Спустя некоторое время styled-components вежливо намекнёт, что так делать не стоит, прямо в консоли браузера:
Для этого случая нам предлагают использовать инлайновые стили, но по прежнему они спрятаны за абстракцией в виде пропсы position , за счёт чего стили отделены от логики:
И самая главная мощь тут заключается в том, что CSS-переменные действуют каскадно!
То есть мы можем разработать компонент, состоящий из нескольких вложенных друг в друга HTML-элементов, установить значение СSS-переменной на корневом элементе и использовать его в потомках:
При большом желании можно даже сохранять данные в СSS-переменных:
На самом деле вся статья задумывалась, чтобы показать, что в 2023 году у СSS-in-JS решений практически не осталось преимуществ перед обычным СSS в отдельном файлике и их использование не всегда оправдано.