- CSS-in-JS — мифы и реальность (на примере styled-components)
- История Css и JavaScript
- А что же с CSS?
- Styled-components
- Миф #1: styled-components решает проблемы глобального пространства имен и конфликтов стилей
- Миф 2: Использование styled-components дает возможность получать более компактный код
- Миф 3. Использование styled components вынуждает больше думать о семантике
- Миф 4: Проще расширять стили
- Миф 5: Облегчается условная стилизация компонентов
- Миф 6: Улучшается организация кода
- Миф 7: «Developer Experience (DX) » становится прекрасным. Инструмент потрясающий!
- Миф 8: Все становится «шустрее», все становится «легче»
- Миф 9: Появляется возможность разработки «responsive» компонентов
- Минуточку, однако!
- Пара мнений от заинтересованных лиц
- Talia Marcassa: Что мы нашли разочаровывающим в styled-components?
- Prometheus: В итоге что?
- И в заключение, слово автору:
- Gajus Kuizinas: — Так что, все-таки, использовать?
- Javascript Set CSS Set CSS styles with javascript
- 2. Global styles
- 3. CSSOM insertRule
- 4. Constructable Stylesheets (July 2019 update)
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?
Проблема обычного CSS состоит в том, что он был создан в эру, когда веб состояла из документов. Web была создана для обмена по преимуществу научными документами в 1993 году и CSS был введен, как решение для стилизации этих документов. Однако, сегодня мы разрабатываем развитые, интерактивные, ориентированные на пользователя приложения, а CSS просто не предназначен для этого.
CSS уже учитывает все требования современных пользовательских интерфейсов. Количество новых функций, реализованных в последнее десятилетие таково, что их все невозможно здесь даже перечислить (pseudo-classes, pseudo-elements, CSS variables, media queries, keyframes, combinators, columns, flex, grid, computed values, …).
С точки зрения пользовательского интерфейса, «component» — это изолированный фрагмент документа (- это «component»). CSS создан для стилизации документов, а документ охватывает все компоненты. В чем же проблема?
Как говорится: «Используйте правильный инструмент для работы».
Styled-components
styled-components дает возможность написания CSS в JavaScript используя т.н. тегированные шаблонные строки. Библиотека удаляет сопоставление между компонентами и стилями — компонент превращается в конструкцию с низкоуровневой стилизацией, например:
// Create a react component that renders an which is // centered, palevioletred and sized at 1.5em const Title = styled.h1` 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 дает возможность получать более компактный код
В подтверждение часто приводят пример:
Прежде всего — это не имеет значения. Разница незначительна.
Во-вторых, это неправда. Общее количество символов зависит от имени стиля.
То же самое применимо и к созданию стилей, что мы увидим позже в этой статье
(Миф5: styled-components облегчает условную стилизацию компонентов). styled-components выигрывает в краткости только в случаях самых базовых компонентов.
Миф 3. Использование styled components вынуждает больше думать о семантике
Сам первоначальный посыл ошибочен. Стилизация и семантика представляют собой разные проблемы и требуют различных решений. Прочтите, например, это Adam Morse (mrmrs).
Семантика занимается применением правильных тегов для разметки. А вы знаете, какие HTML теги будут использованы для рендеринга такого компонента? Нет, не знаете.
Cравните:
Миф 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
И чем проще первый вариант?
Миф 5: Облегчается условная стилизация компонентов
Идея состоит в том, что вы можете стилизовать элементы используя props, например:
Это имеет смысл в React. В конце концов, поведение компонента контролируется через props. Есть ли смысл в прямой привязке prop значений к стилям? Может быть. Но давайте рассмотрим имплементацию такого компонента:
styled.Button` background: $ props.primary ? '#f00' : props.secondary ? '#0f0' : '#00f'>; color: $ props.primary ? '#fff' : props.secondary ? '#fff' : '#000'>; opacity: $ 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
В этом случае, 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, а инструментам отведите роль пространства имен и сборщика — тогда будет всем счастье…
И в заключение, слово автору:
Gajus Kuizinas: — Так что, все-таки, использовать?
- Еще слишком рано говорить о Shadow DOM, ввиду недостаточно глобальной поддержки.
- Используйте CSS с каким-либо соглашением об именовании (например BEM).
- Если вас волнует проблема коллизий имен классов или вы слишком ленивы, чтобы использовать BEM, используйте CSS Modules.
- Если вы работаете с React — рассмотрите возможность использования babel-plugin-react-css-modules.
- Если же вы работаете с React native, styled-components — это то, что надо.
Javascript Set CSS Set CSS styles with javascript
2. Global styles
var style = document.createElement('style'); style.innerHTML = ` #target < color: blueviolet; >`; document.head.appendChild(style);
3. CSSOM insertRule
var style = document.createElement('style'); document.head.appendChild(style); style.sheet.insertRule('#target ');
While it might look similar to the 2nd option, it’s definitely different.
As you can see in Chrome devtools, tag is empty, but the style (darkseagreen color) is applied to the element. Also the color can’t be changed via devtools because Chrome doesn’t allow editing dynamic CSS styles. Actually such behavior was the motivation to write this post. A popular CSS-in-JS library Styled Components use this feature to inject styles in production mode because of performance. This feature might be undesirable in specific projects or environments and some folks complain about it in the project’s issues.
4. Constructable Stylesheets (July 2019 update)
// Create our shared stylesheet: const sheet = new CSSStyleSheet(); sheet.replaceSync('#target '); // Apply the stylesheet to a document: document.adoptedStyleSheets = [sheet];
More details are here.
This option is only valid for Chrome, so use with caution. Do you know other options to add styles with javascript? What is your preferred option these days? Thanks for reading!