Что такое CSS-in-JS и чем отличается от обычного CSS
Стилизация страниц всегда происходит с помощью CSS. В веб-разработке принято разделять HTML и CSS файлы, подключая их друг к другу. Стилизация с использованием JavaScript (JS) в стандартных ситуациях происходит в тех случаях, когда требуется прописать изменение стилей при определенных условиях взаимодействия. Например, пользователь нажал на кнопку и появился какой-нибудь дополнительный блок, который по умолчанию скрыт. Подход CSS-in-JS предполагает вместо стандартных CSS-файлов со стилями использовать скриптовые файлы, где будут также прописываться стили.
Далее разберемся, какие особенности есть у подхода CSS-in-JS, когда он оправдан.
Различия CSS и JavaScript
Они очевидны:
- JS – это язык программирования. Его функционал позволяет задавать условия, получать и менять переменные в зависимости от условий. Однако сам по себе он не предназначен для разметки и стилизации. В веб-разработке он служит чем-то вроде “элемента интерактивности”, так как позволяет задать модель поведения стилей в зависимости от тех или иных условий.
- CSS – это язык разметки. Изначально в нем нельзя задавать никаких условий и переменных, хотя в новых версиях эта возможность постепенно начинает реализовываться. Если использовать только CSS для оформления страницы, то вы, конечно же, сможете создать красивый и удобный интерфейс, но он не будет интерактивным.
Связка CSS и JavaScript позволяет добиться интерактивности и удобства пользовательского интерфейса.
Что такое CSS-in-JS
CSS-in-JS иногда еще называют JSS, хотя это название отдельной библиотеки, а не технологии. Главная особенность заключается не только в том, что стилизация происходит в скриптовых файлах с расширением .js, но и в том, что сам язык JavaScript используется для описания стилей в удобном и декларативном виде. Подобный подход реализован во многих популярных библиотеках и фреймворках. Например, в React большая часть работы происходит со styled-components – это элементы CSS-in-JS.
Вот пример использования такого компонента:
// Create a <Title> react component that renders an <h2> which is
// centered, palevioletred and sized at 1.5em
const Title = styled.h2`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
Здесь создается заголовок h2 на основе данных, содержащихся внутри тега <title>. К нему сразу же задаются стили, которые будут меняться в зависимости от определенных условий.
Примечательно, что эффективно использовать CSS-in-JS без каких-то сторонних библиотек не получится, так как для его корректной работы требуется развертывание вспомогательных файлов. Все это есть внутри библиотек.
Преимущества CSS-in-JS
У этой технологии есть собственный перечень весомых преимуществ:
- Компонентный подход. В случае работы с чистым CSS для каждого более-менее важного элемента на странице, например, секции, рекомендуется создавать отдельный файл. Когда речь идет о большом проекте, то таких файлов становится слишком много, а если писать все в одном файле, то в нем будет сложнее ориентироваться, следовательно, поддержка будет осложнена. В случае с CSS-in-JS используется принцип модульности, что позволяет избавиться от большого количества файлов и сделать структуру проекта чуть проще.
Файловая структура при задании стилей через обычный CSS
- Активно используются возможности JavaScript. Это значит, что вам будет значительно проще задавать условия изменения стилей, делая интерфейс более интерактивным.
- Можно менять стандартную логику CSS. Простой пример: свойства, которые не заданы явно, наследуются от родительского элемента. Иногда это мешает процессу верстки. Благодаря тому, что в CSS-in-JS можно задавать свои правила, вы можете изолировать как группу элементов, так и вообще весь документ, отключив для них наследование свойств родителя.
- Селекторам можно ограничить область видимости. Проблема с уникальными именами (они же селекторы) возникает в любом более-менее сложном проекте и/или в ситуациях, когда к проекту требуется добавить большой сторонний код. Происходит коллизия селекторов, из-за чего стили перестают отображаться корректно. В JSS можно настроить автоматическую генерацию уникальных названий селекторов или просто ограничить область видимости, благодаря чему даже если в документе и будет два одинаковых селектора, то в конфликт друг с другом они вступать не будут.
- Отличная совместимость как JS, так и CSS свойств между собой. Помимо простых свойств полностью совместимы константы и функции. Плюс, они еще и взаимозаменяемы.
- В DOM попадают только стили, использующиеся у отображенных в данный момент на экране элементов. Это уменьшает время, необходимое для загрузки страницы и вообще сильно облегчает ее.
- Есть возможность тестировать работоспособность CSS в виде модулей, в том числе изолированных. Такой подход позволяет оперативнее обнаружить ошибки и исправить их с минимальным риском вызвать появление других ошибок.
Недостатки CSS-in-JS
Основная их масса связана в первую очередь с необходимостью обучения и формированием нестандартного подхода к разработке:
- Требуется освоить новый подход. Знать по отдельность CSS и JavaScript будет недостаточно, хотя это поможет в освоении. Основная проблема в том, что чистый подход CSS-in-JS практически не используется в разработке, а только вкупе со сторонними библиотеками или фреймворками, поэтому изучать желательно их.
- Придется привыкать к новым зависимостям и логике. Они отличаются от стандартного CSS. Сделано это для упрощения разработке, однако быстро адаптироваться к изменению базовых принципов получается далеко не у всех разработчиков.
Пример записи кода формата CSS-in-JS
- Потребуется изучать дополнительные библиотеки и фреймворки. Так как CSS-in-JS не используется в отрыве от сторонних инструментов, то для эффективной работы придется осваивать и их. Хотя бы на базовом уровне.
- Скрипты, разметку и стилизацию придется вести в одном файле. С одной стороны это может упростить процесс написания кода, так как не требуется создания кучи вспомогательных файлов под разные задачи, но с другой стороны код, сваленный в один файл вызывает множество неудобств.
В несложных проектах, где не требуется серьезной интерактивности, например, в Landing Page, оправданно использовать стандартный CSS с препроцессорами. Они очень легко осваитваются и дают некоторые дополнительные фишки, которые есть в JSS, например, возможность создавать переменные.
Когда использовать CSS, а когда JSS
При всех своих преимуществах, CSS-in-JS далеко не всегда рекомендуется использовать. Вот перечень типов проектов, использование в которых JSS оправдано:
- Разработка ведется с использованием динамических библиотек и фреймворков, например, React, Vue, JSS (это еще и библиотека) и подобных. Вся логика работы с этими инструментами строится на использовании подхода CSS-in-JavaScript, поэтому работать с ним будет необходимо в любом случае.
Пример кода из React
- Требуется высокий уровень интерактивности. Плотная интеграция CSS с JavaScript позволяет упростить разработку отзывчивых пользовательских интерфейсов, чем классический подход.
- По тем или иным причинам требуется использовать модульную архитектуру в процессе разработки. Это значит, что обязательно придется прибегать как раз к тем библиотекам, в основе которых находится принцип CSS-in-JS.
В остальных случаях будет разумнее вести разработку с использованием стандартного CSS и JS.
Популярные мифы и заблуждения
CSS-in-JS появился достаточно давно, плюс, он в том или ином виде распространен в популярных библиотеках и фреймворках. Тем не менее, в среде разработчиков есть популярные заблуждения.
Заблуждение 1: Только CSS-in-JS способен корректно решить проблему конфликта имен и стилей
Нет, не только он, хотя эта особенность и является одним из его весомых преимуществ. Однако это далеко не безальтернативный вариант – есть CSS Modules, Shadow DOM, соглашения по наименованиям BEM, различные соглашения внутри команды разработчиков. Да, их использование не всегда удобно, так как иногда требуется отдельное подключение и настройка, но альтернатива styled-components все равно есть.
Заблуждение 2: styled-components позволяют получать более компактный код
Не во всех ситуациях. Дело в том, что общее количество символов и строк будет зависеть от длины имен, сложности обозначаемых условий, наличия разных дополнений. Выигрыш может быть только при использовании самых базовых компонентов и примитивных условий. Также компактный код не гарантирует удобство чтения и/или более лучшую оптимизацию – современное интернет-соединение без проблем проработает несколько лишних килобайт данных.
Пример записи styled-components
Заблуждение 3: Упрощается расширение стилей
Только в случаях, когда расширение носит серьезной и глобальный характер. Вот пример с кнопкой:
const Button = styled.button`
padding: 10px;
`;
const TomatoButton = Button.extend`
color: #f00;
`;
Так выглядит код в JSS. Здесь добавляется цвет для кнопки. Но вот такой же код в классическом CSS:
button {
padding: 10px;
}
button.tomato-button {
color: #f00;
}
Первый вариант смотрится сложнее. Упрощение в расширение стилей с использованием CSS-in-JS можно добиться только в случаях, когда требуется задать сложные стили с определенными условиями для расширения. В обычных ситуациях лучше использовать CSS, а если функционала недостаточно, то препроцессоры.
Заблуждение 4: Улучшается организация кода
Основной аргумент здесь такой: написаний разметки, стилей и скриптов в одном файле для конкретного компонента делает организацию рабочего пространства более удобной. Это действительно может улучшить организацию, но чаще приводит к появлению беспорядочного набора кода, каждый кусок которого может отвечать за абсолютно разные задачи. Пускай создание специализированных файлов и их связка друг с другом требует времени, она вносит гораздо больше порядка в проект, чем написание кода, пускай разделенного на блоки, в одном файле.
Хотя некоторым разработчикам может быть действительно привычнее и удобнее организовывать все в одном файле, нежели создавать иерархию из нескольких в зависимости от их задач.
Заблуждение 5: Процесс разработки очень удобен
Нужно только к нему приноровиться. Возможно, тем, кто работает преимущественно с фреймворками и разными вспомогательными библиотеками процесс разработки действительно покажется более удобным. Однако для тех, кто привык к классической верстке сразу становятся заметны несколько проблем:
- Любая ошибка в стилях приводит к невозможности корректной работы всего приложения или сайта. Системное сообщение об ошибке часто в таких ситуациях очень длинное и не очень понятное – не сразу можно догадаться, что проблема в стилях. В CSS же ошибка в стиле приведет к неправильному отображению элемента, в стилях которого была допущена ошибка, но не более. Плюс, по этому элементу и его поведению будет очень легко вычислить в какой части кода была допущена ошибка.
- В CSS у каждого элемента легко отследить className. При использовании же styled-components такой возможности нет, поэтому придется постоянно переключаться между React element tree и DevTools DOM tree.
Заблуждение 6: Ускоряется работа приложения
Это не так и вот почему:
- Чтобы styled-components отобразились в браузере они должны быть изначально добавлены в DOM и только оттуда выведены в браузере. Это дополнительное время, пускай и занимающее доли секунды. Также это усложнение общей цепочки, что повышает риск некорректного выведения, так как на этом из этапов цепи может произойти ошибка.
- Так как скрипты, стили и разметка находятся в одном файле, то их кеширование будет занимать больше времени, следовательно, при первом посещении страница будет грузиться дольше.
- Анимация возможна только через keyframes.
Заключение
CSS-in-JavaScript это не новая технология, которая применяется преимущественно при работе с фреймворками и разработке сложных сайтов и приложений. У нее есть свои преимущества, но для тех разработчиков, кто привык делать классическую верстку с отдельными файлами, здесь будет больше минусов.
CSS-in-JS — мифы и реальность (на примере styled-components) / Хабр
CSS-in-JS, будучи не совсем новой технологией и реализованной во множестве библиотек, до сих пор вызывает сомнения и споры в целесообразности ее использования. Свои точки над «i» в спорах о CSS-in-JS в общем, и о styled-components в частности, расставил еще год назад, ( 27 Apr 2017 ), и Gajus Kuizinas, автор react-css-modules и babel-plugin-react-css-modules, во все еще, на мой взгляд, актуальной публикации «Прекратите использовать CSS-in-JavaScript в веб-разработках».
Ниже предлагается слегка сокращенный ее перевод с некоторыми добавлениями и выводами:
CSS никуда не уходит. Во множестве проектов выбор в пользу стилизации в JavaScript делается ошибочно. Мы приведем перечень распространенных заблуждений(мифов) и соответствующих им решений посредством CSS.
История Css и JavaScript
CSS был создан для описания представления документа, написанного на языке разметки. JavaScript был создан, как «язык-клей» для сборки компонентов, таких, как изображения и плагины. Спустя годы, JS рос и изменялся, приспосабливаясь ко все новым сферам применения. И, как результат, мы сегодня живем в эру одностраничных приложений (SPA), приложений собранных из компонентов.
А что же с CSS?
Приведем цитату из документации styled-components:
Проблема обычного CSS состоит в том, что он был создан в эру, когда веб состояла из документов. Web была создана для обмена по преимуществу научными документами в 1993 году и CSS был введен, как решение для стилизации этих документов. Однако, сегодня мы разрабатываем развитые, интерактивные, ориентированные на пользователя приложения, а CSS просто не предназначен для этого.
Это не так.
CSS уже учитывает все требования современных пользовательских интерфейсов. Количество новых функций, реализованных в последнее десятилетие таково, что их все невозможно здесь даже перечислить (pseudo-classes, pseudo-elements, CSS variables, media queries, keyframes, combinators, columns, flex, grid, computed values, …).
С точки зрения пользовательского интерфейса, «component» — это изолированный фрагмент документа (<button />- это «component»). CSS создан для стилизации документов, а документ охватывает все компоненты.
Как говорится: «Используйте правильный инструмент для работы».
Styled-components
styled-components дает возможность написания CSS в JavaScript используя т.н. тегированные шаблонные строки. Библиотека удаляет сопоставление между компонентами и стилями — компонент превращается в конструкцию с низкоуровневой стилизацией, например:
// Create a <Title> react component that renders an <h2> which is // centered, palevioletred and sized at 1.5em const Title = styled.h2` font-size: 1.5em; text-align: center; color: palevioletred; `;
styled-components сегодня пользуется популярностью и известна, как новый способ стилизации компонентов в React, хотя иногда ее представляют даже, как «вершину развития CSS»:
CSS Evolution: From CSS, SASS, BEM, CSS Modules to Styled Components.
Но давайте уясним следующее: styled-components — это всего лишь надстройка над CSS. Эта библиотека разбирает стили CSS, определенные вами в JavaScript и создает соответствующие JSX элементы.
Популярность styled-components сопряжена со множеством заблуждений. Обзор ответов программистов (найденных на IRC, Reddit и Discord) на вопрос о причинах, побудивших их применить эту библиотеку, позволил составить список наиболее упоминаемых. Назовем их мифами.
Миф #1: styled-components решает проблемы глобального пространства имен и конфликтов стилей
Это миф, потому что звучит так, якобы упомянутая проблема еще никак не решалась. Однако CSS Modules, Shadow DOM и бесчисленные соглашения по именованиям ( такие как BEM) предложили решения проблемы давным давно.
styled-components (точно так же, как и CSS modules) снимает с человека проблему ответственности за наименования. Человеку свойственно ошибаться, компьютеры ошибаются не столь часто.
Сам по себе, это еще недостаточно веский довод для использования styled-components.
Миф 2: Использование styled-components дает возможность получать более компактный код
В подтверждение часто приводят пример:
<TicketName></TicketName> <div className={styles. ticketName}></div>
Прежде всего — это не имеет значения. Разница незначительна.
Во-вторых, это неправда. Общее количество символов зависит от имени стиля.
<TinyBitLongerStyleName></TinyBitLongerStyleName> <div className={styles.longerStyleName}></div>
То же самое применимо и к созданию стилей, что мы увидим позже в этой статье
(Миф5: styled-components облегчает условную стилизацию компонентов). styled-components выигрывает в краткости только в случаях самых базовых компонентов.
Миф 3. Использование styled components вынуждает больше думать о семантике
Сам первоначальный посыл ошибочен. Стилизация и семантика представляют собой разные проблемы и требуют различных решений. Прочтите, например, это Adam Morse (mrmrs).
Тем не менее, рассмотрим:
<PersonList> <PersonListItem> <PersonFirstName>Foo</PersonFirstName> <PersonLastName>Bar</PersonLastName> </PersonListItem> </PersonList>
Семантика занимается применением правильных тегов для разметки. А вы знаете, какие HTML теги будут использованы для рендеринга такого компонента? Нет, не знаете.
Cравните:
<ol> <li> <span className={styles.firstName}>Foo</span> <span className={styles.lastName}>Bar</span> </li> </ol>
Миф 4: Проще расширять стили
Сравните:
const Button = styled.button` padding: 10px; `; const TomatoButton = Button.extend` color: #f00; `;
Замечательно! Но то же самое вы можете сделать и в CSS (или использовать CSS module composition, а также SASS inheritance mixin @extend).
button { padding: 10px; } button.tomato-button { color: #f00; }
И чем проще первый вариант?
Миф 5: Облегчается условная стилизация компонентов
Идея состоит в том, что вы можете стилизовать элементы используя props, например:
<Button primary /> <Button secondary /> <Button primary active={true} />
Это имеет смысл в React. В конце концов, поведение компонента контролируется через props. Есть ли смысл в прямой привязке prop значений к стилям? Может быть. Но давайте рассмотрим имплементацию такого компонента:
styled.Button` background: ${props => props.primary ? '#f00' : props.secondary ? '#0f0' : '#00f'}; color: ${props => props.primary ? '#fff' : props.secondary ? '#fff' : '#000'}; opacity: ${props => props.active ? 1 : 0}; `;
Создание условных стилей при помощи JavaScript дает массу возможностей. Однако, это также означает, что стили будет намного сложнее интерпретировать. Сравните с CSS:
button { background: #00f; opacity: 0; color: #000; } button.primary, button.seconary { color: #fff; } button.primary { background: #f00; } button.secondary { background: #0f0; } button.active { opacity: 1; }
В этом случае, CSS короче (229 символов против 222) и проще для понимания (субъективно). Более того, в CSS вы могли бы использовать препроцессор, чтобы получить еще более короткий и сгрупированный результат:
button { background: #00f; opacity: 0; color: #000; &. primary, &.seconary { color: #fff; } &.primary { background: #f00; } &.secondary { background: #0f0; } &.active { opacity: 1; } }
Миф 6: Улучшается организация кода
Некоторые говорят о том, что им нравится styled-components, потому что появляется возможность размещать стили и скрипты в одном файле. Можно понять, что наличие множества файлов для одного компонента может показаться утомительным, но впихивание стилей и разметки в единый файл — это ужасно. Это не только системе контроля версий усложнит отслеживание изменений, но и приведет к бесконечному «скроллингу» на любом элементе посложнее простой кнопки.
Если же вам непременно нужно разместить CSS и JavaScript в одном и том же файле, попробуйте css-literal-loader. Последнее позволит вам собирать стили во время «build» посредством extract-text-webpack-plugin и использовать стандартную конфигурацию лоадера для обработки CSS.
Миф 7: «Developer Experience (DX) » становится прекрасным.
Инструмент потрясающий!Очевидно, что вы не использовали styled-components.
- Если что-то пошло не так со стилями, все приложение «падает» с длинной стековой трассировкой ошибки. Противоположность этому — CSS, где ошибка в стилях приведет просто к неправильному отображению элемента.
- У элементов отсутствуют различаемые className, поэтому при отладке придется бесконечно переключаться между React element tree и DevTools DOM tree.
- И хотя плагины для линтинга, подсветки кода, автозавершения кода, и другие подобные «прелести» уже существуют и для styled-components, они все еще могут быть недоступны для вашего IDE. Если вы работаете с финансами в правительственном агенстве, есть шансы, что Atom IDE будет недоступна.
Миф 8: Все становится «шустрее», все становится «легче»
- Как выяснилось, styled-components стили не могут быть экстрагированы в статический
CSS файл (например используя extract-text-webpack-plugin). Это значит, что браузер не сможет начать интерпретацию стилей до тех пор, пока styled-components не «распарсит» их и не добавит в DOM. - Совмещение стилей и скриптов в одном файле означает, что раздельное их кеширование невозможно.
- Природа styled-components такова, что все они обернуты в дополнительный HOС. А это ненужное понижение производительности. Такой же недостаток привел к прекращению поддержки react-css-modules и появлению babel-plugin-react-css-modules.
- Из-за того же HOC, серверный рендеринг приводит к значительно большему размеру разметки документа.
- Даже и не пробуйте анимировать компоненты используя динамические стили, а не keyframes.
Миф 9: Появляется возможность разработки «responsive» компонентов
Речь идет о способности стилизовать компонент на основе окружающей среды, например, размеров родительского контейнера, количества наследников и т. д.
Прежде всего, styled-components не имеют ничего общего с этим.
Это выходит за рамки проекта. В данном случае лучше прямо установить значения стиля компонента, чтобы избежать дополнительных нагрузок на процессор.
Минуточку, однако!
Большинство, если не все из этих проблем, могут быть решены в перспективе то ли сообществом, изменениями в React или в самой styled-components. Только зачем? CSS уже широко поддерживается, имеется солидное сообщество и… просто работает.
Но не нужно всегда избегать применения CSS-in-JavaScript или styled-components.
Есть кое-что, что делает styled-components хорошей библиотекой — это лучшая кросс-платформенная поддержка.
Просто не используйте styled-components исходя из ошибочных представлений.
Пара мнений от заинтересованных лиц
Talia Marcassa: Что мы нашли разочаровывающим в styled-components?
Применяя styled-components в нашем проекте мы обнаружили, что имеются некоторые стилевые правила, которые трудно внедрять в styled-components; например, правила, которые управляют размещением элементов на странице ( margins или display свойство). Это трудно поддавалось стандартизации, так что мы по-прежнему были вынуждены в значительной степени опереться на простой CSS для размещения компонентов в потоке элементов.
… хотя и были сложности в применении styled-components, библиотека помогла нам уменьшить кодовую базу.
Prometheus: В итоге что?
(комментарий к «Эволюция CSS: от CSS, SASS, BEM и CSS–модулей до styled-components»)
… Никакая эволюция CSS тут не значится, эволюционируют инструменты.
На мой взгляд, проблемы никакой нету, когда версткой занимается верстальщик, а программист — программированием.
А вот когда программисты занимаются версткой — вот тогда начинается весь этот зоопарк, который вместо ПРОСТОТЫ с дальнейшей поддержкой, дает лишнюю головную боль.
…
Пишите на чистом CSS, а инструментам отведите роль пространства имен и сборщика — тогда будет всем счастье…
И в заключение, слово автору:
Gajus Kuizinas: — Так что, все-таки, использовать?
- Еще слишком рано говорить о Shadow DOM, ввиду недостаточно глобальной поддержки.
- Используйте CSS с каким-либо соглашением об именовании (например BEM).
- Если вас волнует проблема коллизий имен классов или вы слишком ленивы, чтобы использовать BEM, используйте CSS Modules.
- Если вы работаете с React — рассмотрите возможность использования babel-plugin-react-css-modules.
- Если же вы работаете с React native, styled-components — это то, что надо.
Проблемы и преимущества CSS-in-JS
Дискуссия о CSS-in-JS и о том, стоит ли использовать его в своих проектах, ведется уже почти полвека. С ростом популярности фреймворков JavaScript, таких как React, Angular и Vue, многие организации предпочитают использовать CSS-in-JS в производстве. Огромные компании, такие как Reddit, Atlassian и Patreon, сделали шаг к решению CSS-in-JS. Многие наши клиенты в Sparkbox выбирают аналогичный подход.
Как человек, который любит Sass больше, чем любой другой веб-язык, я сначала не решался использовать CSS-in-JS. Разве это не добавит веса моему проекту? Разве это не чрезмерная инженерия? Многие разработчики CSS и SCSS разделяют эти опасения. На самом деле, многие люди, которые научились любить CSS без JavaScript, отказываются от идеи CSS-in-JS. И точно так же многие разработчики JavaScript не могут понять, почему вам не нужен CSS-in-JS.
Тем не менее, вот я здесь, последние 2 с лишним года использую исключительно CSS-in-JS в средах корпоративных систем проектирования. Я думаю, что это довольно солидный выбор. Почему?
Какую проблему пытается решить CSS-in-JS?
Жалобы разработчиков на CSS в основном можно объединить в одну программную проблему: все в CSS «глобально». Это означает, что все правила CSS одинаково доступны для всего кода. CSS полагается на «каскадную» часть «каскадных таблиц стилей» для определения приоритетного порядка правил. Если вы когда-либо сталкивались с проблемой CSS, связанной со «специфичностью», «иерархией» или «каскадом», это, вероятно, означает, что у вас была проблема с глобальной областью действия.
В Sparkbox и в более широком веб-сообществе веб-интерфейса мы устраняем эти типы глобальных ошибок, связанных с областью видимости, придерживаясь искренней стратегии организации нашего CSS. Например, ITCSS и BEM создают псевдообласти объектов макета, блоков/компонентов, элементов, настроек, инструментов и т. д. Правило CSS BEM ( .block__element--modifier
) ограничено элементом html с .block
имя класса.
Целые системы дизайна и CSS-фреймворки (например, Bootstrap или Tailwind) созданы для решения этих проблем путем привязки стилей к компонентам, токенам или служебным классам. Многие библиотеки CSS-in-JS утверждают, что предлагают лучший способ, напрямую связывая область действия правила стиля CSS с «компонентом» JavaScript, который он означает для стиля.
Я не эксперт по каждой отдельной библиотеке стилей JavaScript, так что принимайте это как хотите. Большая часть моего опыта связана с эмоциями. Это отличный инструмент, популярный у многих наших клиентов.
Какие преимущества дает CSS-in-JS?
CSS-in-JS обеспечивает более «атомарный» способ применения стилей только к тем компонентам, которые их используют. Однако среди разработчиков CSS распространено заблуждение, что это означает встраивание всех наших стилей. Многие библиотеки компилируют CSS из файлов JavaScript в уникальное имя класса, которое добавляется к соответствующему тегу. Например, следующий код кнопки:
<кнопка css={css` фоновый цвет: rebeccapurple; белый цвет; &: фокус { контур: 2px пунктирная слива; } `} > Некоторый текст кнопки кнопка>
Можно было скомпилировать в DOM что-то вроде этого, встроенные стили не найдены:
Конкретное ограничение стилей на уровне компонентов — это то, как CSS-in-JS решает проблему иерархии. Вот почему многие разработчики React (и подобных) любят использовать его в своих кодовых базах; все стили находятся непосредственно в вашем каталоге компонентов React.
Одной из самых популярных статей Sparkbox Foundry за все время по-прежнему является статья Итана Мюллера 2014 года, Именование элементов CSS — это действительно сложно . CSS-in-JS делает так, что у вас нет , чтобы так тщательно называть вещи. Вы по-прежнему можете использовать имена, если хотите, но из-за области действия на уровне компонентов вы можете называть вещи волей-неволей, не опасаясь коллизий стилей. Такие имена, как «кнопка» или «заголовок», можно использовать в нескольких файлах, и на странице ничего не сломается.
Еще одно распространенное заблуждение об использовании CSS-in-JS заключается в том, что это сильно влияет на производительность. В зависимости от размера ваших таблиц стилей, это может быть преимуществом. Как и в React, только компоненты, отображаемые на странице, будут отображать свой CSS. Вам больше не нужно беспокоиться о загрузке лишних стилей. Скорее всего, если вы используете фреймворк JavaScript, размер библиотеки стилей редко будет достаточно большим, чтобы что-то изменить. Однако, если это действительно важно, такие библиотеки, как Emotion, часто имеют некоторые встроенные возможности рендеринга на стороне сервера.
Какие проблемы создает или игнорирует CSS-in-JS?
Одна из главных проблем CSS-in-JS заключается в том, что сам код начинает больше походить на JavaScript. Это может быть трудно преодолеть, если в вашей команде полно разработчиков CSS или Sass, которым неудобно писать JavaScript. Тем не менее, это может иметь скрытое преимущество, если в вашей команде полно разработчиков JavaScript, которым не нравится синтаксис CSS, но имейте в виду, что написание качественного CSS-in-JS по-прежнему требует глубокого понимания фундаментальных навыков CSS.
Как и со всеми инструментами, вы должны делать то, что лучше всего подходит для вашего проекта и команды. Если использование CSS-in-JS заставляет вашего блестящего разработчика SCSS писать посредственный CSS-in-JS, вы теряете блестящий SCSS! Тем не менее, есть определенные библиотеки CSS-in-JS, синтаксис которых очень похож на написание CSS (и даже SCSS!). Таким образом, ваша команда должна быть в состоянии вернуться к своим потрясающим «я» после начального периода обучения.
Еще одна сложность, связанная с CSS-in-JS, заключается в том, что преобразование существующего кода, вероятно, требует немалых усилий. Представьте, что вы переписываете и дублируете всю кодовую базу CSS для каждого компонента. Если это звучит ужасно, возможно, оно того не стоит. Только ваша команда может решить, «стоит ли сок выжимать».
CSS-in-JS также часто не имеет смысла, если ваша страница изначально имеет ограниченный JavaScript. Сладкая зона для CSS-in-JS — это проект, построенный на основе JavaScript, который использует структуру компонентов, часто React. У Vue и Angular есть свой ответ на проблему с областью действия CSS. Vue даже делает что-то подобное, используя «стили с ограниченной областью действия». Из-за этого библиотеки CSS-in-JS часто создаются с учетом React. Если вы не используете фреймворк JavaScript, добавьте большую библиотеку CSS-in-JS, чтобы иметь возможность писать CSS в . js
файлов, вероятно, слишком сложны.
Какую библиотеку использовать?
Итак, в вашей команде есть в основном разработчики JavaScript, которые создают приложение React — основной сценарий для CSS-in-JS. Теперь о выборе библиотеки.
Реальный выбор здесь состоит в том, чтобы решить, хотите ли вы использовать «объект стиля», который выглядит как объект JavaScript, или вы предпочитаете писать что-то, что больше похоже на CSS или SCSS, но с преимуществами CSS-in-стиля. JS.
Использование объекта стиля имеет некоторые недостатки. Синтаксис CSS поддерживается не всегда, поэтому такие правила, как медиа- и функциональные запросы, могут сильно отличаться. Вам также придется переименовать все свойства CSS в camelCase (например, font-color
становится fontColor
), и правильный перевод не всегда очевиден.
Строковые шаблоны CSS — это именно то, на что они похожи: строковый шаблон компилируется непосредственно в CSS. Некоторые функции Sass встроены в Emotion и другие библиотеки, например, селектор и
, а также возможность вложения компонентов и медиа-запросов. Выбор библиотеки на основе строковых шаблонов не только упрощает адаптацию разработчикам CSS, но также может быть огромным преимуществом, если вы решите перенести существующий CSS. Просто скопируйте и вставьте.
Опять же, Emotion — мой старый фаворит здесь — позволяет вам выбрать любой из них, но это не единственная библиотека. Styled-Components имеют так много одинаковых функций, что я бы назвал их взаимозаменяемыми. Если размер пакета имеет значение, Emotion v10 весит около 6 КБ (хотя Emotion v11 — классный 216b). Styled-Components добавляет около 15kb. Также есть модули CSS (~10 КБ), JSS (6 КБ) или React-JSS (20 КБ), React-with-Styles (8 КБ) и множество других вариантов.
Чтобы узнать нюансы каждой библиотеки, я нашел полезным инструмент под названием CSS-in-JS Playground.
Большая часть моего личного опыта разработки связана с внедрением крупномасштабных систем проектирования для корпоративных организаций. Многие из этих систем проектирования были созданы для поддержки библиотек компонентов React, часто встроенных в Storybook и доставляемых подписчикам через модули npm. И это лучший сценарий, в котором эта фанатка SCSS поддерживает использование CSS-in-JS поверх SCSS. Если вы думаете о запуске новой системы дизайна на основе React или обновлении существующей системы дизайна для лучшей поддержки React, CSS-in-JS может стать хорошим выбором.
Если ваша дизайн-система похожа на Bootstrap, то есть элементы стилизуются путем добавления числовой утилиты или классов токенов, многие фреймворки CSS-in-JS по-прежнему поддерживают стилизацию с помощью имен классов. Можно сохранить систему, основанную на именах классов, и конвертировать в CSS-in-JS один компонент за раз. Кроме того, эфемерная природа CSS-in-JS означает, что сгенерированные имена классов могут меняться между сборками, поэтому вы можете в любом случае использовать согласованную систему имен классов для обеспечения доступности.
Доставка дизайн-системы с функциями JavaScript или в JavaScript Framework может быть сложной задачей. Исторически я доставлял SCSS через npm, который должен был быть связан с node_modules
непосредственно в базовой таблице стилей SCSS. Это неплохое решение, но оно открывает кодовую базу для коллизий и утечек области видимости.
При использовании CSS-in-JS все стили компонентов библиотеки дизайн-системы связаны и изолированы с помощью компонента JavaScript. Их по-прежнему можно доставлять через пакет npm, но теперь, когда компонент включается на страницу через JavaScript import
, все стили, которые нужны компоненту, также поставляются вместе с ним.
CSS-in-JS также позволяет «расширять» стили системы дизайна в пользовательские компоненты. Вместо переменных SCSS это можно сделать с помощью констант JavaScript или объектов или массивов, состоящих из строковых шаблонов или объектов стилей. Реквизиты могут анализировать темы компонентов, такие как темная или светлая для карты или первичная или вторичная для стилей кнопок. Подписчики могут даже передавать пользовательские стили для настройки компонентов или настройки макета в контексте. Это действительно счастливый путь.
Заключение
Мне все же больше нравится писать SCSS. Я по-прежнему считаю, что многие проекты, использующие фреймворк JavaScript и библиотеки, предоставляющие CSS-in-JS, скорее всего, перепроектированы, жертвуя производительностью и доступностью в пользу знакомых или более интересных технологий разработки. Тем не менее, есть столько же проектов и команд, которые сильно выигрывают от фреймворков JavaScript, и даже немалое количество, где CSS-in-JS, вероятно, является «лучшим выбором». Как всегда, только вы можете принять решение, которое лучше всего подходит для вашей кодовой базы.
Краткая история CSS-in-JS: как мы к этому пришли и куда идем | Дэн Уорд
Опубликовано в·
Чтение: 6 мин.·
16 ноября 2017 г. JSВ моей последней статье Я рассказал о том, насколько сложно выбрать методологию или структуру CSS в настоящее время, и объяснил, почему отказ от догм — это одна из самых важных вещей, которые мы можем сделать как сообщество, чтобы делать новые открытия и продвигать развитие CSS.
Javascript делает CSS
Впервые концепцию каскадных таблиц стилей предложил Хокон Виум Ли, работая в ЦЕРН в октябре 1994 года. Позднее CSS был формализован Ли в его докторской диссертации в Университете Осло в 2006 году.
В ходе сессии вопросов и ответов после лекции Ли о CSS, которую он прочитал 16 февраля 2006 г. — за день до защиты диссертации — произошел удивительно пророческий обмен мнениями:
Итан Мансон: основная проблема
, что бы вы ни предложили, потребуется некоторое время, чтобы попасть в
в любом браузере. Я имею в виду, что вы можете предложить его, и если вы действительно хотите, чтобы
стал стандартом, Opera, возможно, заставит его работать к тому времени, когда стандарт
будет одобрен, но другие производители браузеров, вероятно,
, и пока у вас не будет почти всех браузеры работают что-то это
не работает.ХВЛ: Верно. Есть альтернатива, которая будет работать сегодня, и
, которая состоит в том, чтобы извлекать вещи в библиотеки Javascript, которые у вас были хорошо
написанных библиотек Javascript, на которые вы могли бы ссылаться, сегодня у вас бы
они работали даже в IE6. Вам снова пришлось бы зажать нос, некоторым из нас пришлось бы зажать носы, чтобы это произошло, но это
можно было бы сделать и проще. Я думаю, что мы действительно должны
следовать обоим этим путям. Я думаю, нам нужно больше узнать о CSS
, но не задерживать дыхание, чтобы его можно было использовать.Итан Мансон: Что, если бы вы могли сделать переход более плавным? Что если
вы могли бы, это был бы уродливый код, но что, если бы вы могли добавить функции
в CSS, которые вы хотите, но сделать путь, по которому кто-то мог бы
использовать синтаксический анализатор, реализованный в Javascript, для определения наличия этого кода
в CSS и может поддерживать его с помощью библиотеки Javascript?
— Таблицы стилей и проблемы, связанные с динамическими аспектами Интернета
Как мы все знаем, CSS стал методом для определения стиля веб-документа. Он был достаточно мощным, чтобы удовлетворить потребности веб-разработчиков, работающих над всеми типами проектов, и был достаточно доступен для любителей веб-разработки, чтобы приступить к работе без гигантской кривой обучения.
CSS также обеспечил приятное и четкое разделение проблем для каждой части того, что стало святой троицей веб-документов: HTML, Javascript и CSS. HTML управлял структурированием контента, JavaScript обеспечивал поведение, а CSS диктовал, как все должно выглядеть.
Эта установка представляла собой отличное, проверенное в боевых условиях решение для публикации веб-страниц в течение многих лет. Он был надежным, имел низкий барьер для входа и делал веб-разработку доступной. Все было в порядке с всемирной паутиной.
Достижения в JavaScript, однако, со временем представили совершенно новую экосистему разработки. К 2011 году появление фреймворков JavaScript для создания одностраничных приложений начало влиять на ландшафт разработки. AngularJS появился в октябре 2010 года, EmberJS — в декабре 2011 года, ReactJS — в марте 2013 года, VueJS — в феврале 2014 года. в сферу одностраничных приложений по мере роста популярности этих фреймворков. По мере того, как SPA становились все более сложными и поведенческими, пользователи ожидали, что сайты будут иметь все более и более динамичный и многофункциональный опыт.
В ноябре 2014 года инженер Facebook Кристофер Чедо, также известный как Vjeux, выступил с докладом о концепции, которую он назвал CSS-in-JS . Он начал выступление с того, что стало довольно известным слайдом, обрисовывая в общих чертах то, что он видел в качестве основных проблем с CSS, которые необходимо было преодолеть, чтобы разработчики могли разумно поддерживать высокодинамичные веб-приложения, особенно в масштабе:
Vjeux 7 проблем с CSS в Масштаб (https://speakerdeck.com/vjeux/react-css-in-js)С 2014 года многие разработчики работали над тем, чтобы сделать CSS-in-JS реальностью. Обработка CSS с помощью JavaScript обеспечивает уникальное решение этих проблем. Если вы хотите глубже погрузиться в текущие реализации, а также в плюсы и минусы использования методов CSS-in-JS, я настоятельно рекомендую отличную статью 9 Индрека Ласна.0035 Все, что вам нужно знать о CSS-in-JS .
Использование Javascript для применения и управления CSS на первый взгляд кажется нарушением принципа разделения интересов. В отличной работе Криштиану Растелли «Да будет мир» по CSS (статья/видео) он предполагает, что CSS-in-JS поддерживает принцип разделения ответственности. Мы просто должны разделять наши заботы по-другому. Подумайте, разделялись ли задачи по элементам строк вместо технология строк. Мы по-прежнему получаем четкое разделение:
Разделение интересов с другой точки зрения (Да будет мир на CSS)Документ против веб-приложений
«Любой, кто работал с CSS достаточно долго, должен был прийти смириться с его агрессивно-глобальным характером — модель, явно разработанная в эпоху документов, сейчас изо всех сил пытается предложить разумную рабочую среду для современных веб-приложений». [Конец глобального CSS]
В Интернете существует два типа веб-сайтов: те, которые состоят в основном из статического контента (документы), и те, которые в основном интерактивны (веб-приложения). В книге Марка Далглиша «Конец глобального CSS» он утверждает, что спецификация CSS, которая является прямым потомком спецификации, созданной и ратифицированной в конце XIX в. 0 не соответствует потребностям современных веб-приложений.
Создание сайта Document и создание веб-приложения имеют свои собственные потребности. Если традиционный (не CSS-in-JS) CSS соответствует потребностям вашего проекта, продолжайте! В самом деле, даже если вы создаете веб-приложение, существует множество вдумчивых аргументов в защиту традиционного CSS, а не CSS-in-JS.
У каждого проекта есть свои потребности, и у каждого разработчика есть свои предпочтения. Таким образом, вопрос не должен заключаться в том, «выиграет ли CSS-in-JS или традиционный CSS войны CSS?» а скорее «какое решение CSS соответствует потребностям моего проекта?»
Я считаю, что заключительные заявления Криштиану Растелли Да будет мир на CSS выражают это лучше всего, что я читал:
Я не в состоянии влиять на все сообщество, подобное нашему. Но я могу попытаться убедить вас, что есть лучший способ , чем сражаться друг с другом.
Итак, вот мои предложения:
1.