Припиніть використовувати CSS JavaScript у веб-розробці

19

Від автора: CSS нікуди не дівається. Безліч проектів воліють стилізувати документи через JS за нерозуміння. В цій статті зібрані найпоширеніші міфи про використання CSS і JavaScript існуючі рішення цих проблем.

Стаття не націлена нашкодити певних проектів або людям. «CSS в JS» я визначаю, як використання styled-components. Зараз це тренд стилізації компонентів у React.

Історія CSS і JS

Каскадні таблиці стилів (CSS) були створені для опису представлення документа, написаного за допомогою мови розмітки. JS був створений як «єднає мова» для зв’язки компонентів, таких як зображення і плагіни. Йшли роки, JS ріс і мутував під нові приклади використання.

Поява терміна Ajax (2005) – важлива віха. Саме тоді бібліотеки типу Prototype, jQuery, MooTools залучили величезні спільноти до спільного вирішення проблем отримання даних у фоновому режимі і неоднорідності роботи коду в різних браузерах. Так була створена нова проблема – як управляти всіма даними?

Перенесемося в 2010. Backbone.js став стандартом управління станом додатки. Майже відразу після цього з’явилися React і Flux. Так почалася ера односторінкових додатків (SPA) – додатків, які складаються з компонентів.

Що ж з CSS?

У документації до styled-components:

«Проблема чистого CSS полягає в тому, що він створювався в еру, коли веб складався з документів. В 1993 році був створений інтернет для обміну здебільшого науковими документами, і CSS був представлений, як рішення стилізації цих документів. Сьогодні ми створюємо багаті, інтерактивні, user-facing програми, і CSS не призначений для них.»

Не погоджуся.

CSS еволюціонував під вимоги сучасних UI. Кількість нових функцій, що з’явилися за останні 10 років, виходить за рамки розумного (псевдокласи, псевдоелементи, CSS змінні, медіа запити, кейфреймы, комбінатори, колонки, flex, сітки, обчислювані значення…).

З точки зору UI компонент – це ізольований фрагмент документа (button — компонент). CSS придумали для стилізації документів, які цілком складаються із компонентів. Так в чому ж проблема?

Як говориться «використовуйте правильний інструмент для роботи».

Стилізовані компоненти

styled-components дозволяють писати CSS в JS за допомогою шаблонних літералів з тегів. Вони видаляють зв’язок між компонентами і стилями – компонент перетворюється в стильову конструкцію низького рівня.

import React from ‘react’;
import styled from ‘styled-components’;
// Create a react component that an renders

which is
// centered, palevioletred and sized at 1.5 em
const Title = styled.h1`
font-size: 1.5 em;
text-align: center;
color: palevioletred;
`;
// Create a react component that renders with a
// some padding and a background papayawhip
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Use them like any other React component – except they’re styled!
Hello World, this is my first styled component!

Результат:

Припиніть використовувати CSS JavaScript у веб-розробці

styled-components зараз в тренді. З їх допомогою стилізують компоненти в React.

З’ясуємо дещо: styled-components – це просто абстракція високого рівня поверх CSS. Вона лише парсити ваш CSS, написаний в JS, і створює JSX елементи, пов’язані з CSS.

Мені не подобається цей ажіотаж, навколо нього багато непорозумінь.

Я запитав на IRC, Reddit і Discord, чому люди використовують styled-components. Я зібрав список загальних відповідей, чому люди воліють styled-components. Я називаю їх міфами.

Міф №1: вони вирішують проблему глобального простору імен і конфлікти стилізації

Я називаю цю причину міфом, тому що вона звучить так, ніби ця проблема не була вирішена раніше. CSS Modules, Shadow DOM і нескінченна безліч систем іменування (BEM) вирішили цю проблему набагато раніше.

styled-components (як CSS модулі) знімає з людей відповідальність за іменування. Люди роблять помилки, комп’ютери роблять їх менше.

Це не сама хороша причина використовувати styled-components.

Міф №2: styled-components скорочує код

Часто пропонують такий приклад:

По-перше, це зовсім не важливо. Відмінності незначні.

По-друге, це не правда. Кількість символів залежить від імені стилю.

Те ж саме стосується до створення стилів. Це ви побачите нижче в статті (міф №5: так легше стилізувати компоненти за умовою). styled-components виграє в стислості тільки при використанні базових компонентів.

Міф №3: styled components змушує вас більше замислюватися про семантику

Неправильний сам посил. Стилі та семантика представляють різні проблеми і вимагають різних рішень. Процитуємо Adam Morse (mrmrs):

«Семантика контенту ВЗАГАЛІ НЕ ПОВ’ЯЗАНА З ВІЗУАЛЬНИМИ СТИЛЯМИ. Коли в дитинстві я грав в лего, я ніколи не думав «цей блок для двигуна». Я думав «о, круто, це блок 1×4, я можу зробити з ним, що завгодно». Неважливо що я збирав, будь-то підводний база для підводників або літак, я точно знав, як користуватися лего.»

Все ж давайте припустимо, що зв’язок є.

Приклад:

Foo
Bar

Семантика – використання правильних тегів для написання розмітки. Ви знаєте, які HTML теги будуть рендери ці компоненти? Не, не знаєте.

Порівняйте з:

  • Foo
    Bar
  • Міф №4: так легше розширювати стилі

    У v1 ви можете розширювати стилі через конструкцію styled(StyledComponent), v2 представили метод extend для розширення існуючих стилів.

    const Button = styled.button`
    padding: 10px;
    `;
    const TomatoButton = Button.extend`
    color: #f00;
    `;

    Відмінно. Але це можна робити і в CSS (з допомогою CSS module composition або успадкованого Sass міксина @extend).

    button {
    padding: 10px;
    }
    button.tomato-button {
    color: #f00;
    }

    Що легше зробити в JS?

    Міф №5: так легше стилізувати компоненти за умовою

    Суть в тому, що ви можете стилізувати компоненти за їх властивостями.

    У світі React це багато значить. Адже По суті, поведінка компонентів контролюється через властивості. Можна прикріплювати значення властивостей безпосередньо в стилі, чи є в цьому сенс? Можливо. Але давайте подивимося на компонент:

    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};
    `;

    Створення стилів за умовою через JS дає вам велику силу. Але такі стилі також складніше інтерпретувати. Порівняйте з:

    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, тому що вони дозволяють писати стилі і JS в одному файлі.

    Я розумію, що кілька файлів для одного компонента стомлює, однак писати стилі і розмітку в одному файлі – жахлива ідея. Це не тільки ускладнює контроль версій, але вам доведеться довго крутити код на будь-якому компоненті складніше кнопки.

    Якщо вам обов’язково необхідно писати CSS і JS в одному файлі, використовуйте css-literal-loader. Цей інструмент дозволяє витягувати CSS в момент білду з допомогою extract-text-webpack-plugin і використовувати стандартні налаштування завантаження для обробки CSS.

    Міф №7: це покращує DX. Інструменти приголомшливі!

    Ви, швидше за все, не використовували styled-components.

    Коли зі стилями щось йде не так, ламається все додаток з великою логом помилки. Порівняйте з CSS, де помилка стилю просто неправильно відображає елемент.

    У елементів немає розпізнаваних className, тому в дебаге вам залишається лише перемикатися між деревом елементів React і деревом DevTools DOM (v2 це можна вирішити за допомогою babel-plugin-styled-components).

    Немає линтинга (зараз розробляється stylelint plugin).

    Невалідні стилі просто ігноруються (clear: both; float left; color: #f00; не повернуть помилок і попереджень; у мене пішло 15 хвилин в дебаге на проходження трасування стека, навіть після прочитання вихідного коду styled-components). Тільки після того, як я скопіював код в чат і попросив допомогти, хто вказав мені, що немає. Ви ж помітили, так?)

    Підсвічування синтаксису, автозавершення коду та інші тонкощі підтримуються в декількох IDE. Якщо ви працюєте з урядовими і фінансовими агентствами, є ймовірність, що Atom IDE вам не підійде.

    Міф №8: чим менше розмір, тим більше продуктивність

    Як би те ні було, styled-components можна отримати в статичний CSS файл (наприклад, https://github.com/webpack-contrib/extract-text-webpack-plugin).Тобто браузер не почне інтерпретацію стилів, поки styled-components не распарсит їх і не додасть в DOM.

    Відсутність файлів говорить про те, що не можна кешувати окремий CSS і JS

    Всі стилізовані компоненти обертаються в додатковий HoC. Удар по продуктивності незначний. З цієї ж причини я перестав розробляти https://github.com/gajus/react-css-modules (і створив https://github.com/gajus/babel-plugin-react-css-modules).

    З-за HoC рендер на сервері призводить до збільшення розмітки в документі

    Не змушуйте мене запускати компоненти анімації з допомогою динамічних значень стилів або кейфреймов

    Міф №9: дозволяє розробляти адаптивні компоненти

    Йдеться про можливість стилізувати компонент з його оточення, тобто розмірам батьківського контейнера, кількості дочірніх елементів і т. д.

    По-перше, styled-components взагалі з цим не пов’язані. Це за межами проекту. Краще встановлюйте значення style прямо на компонент.

    Елементні запити – цікава проблема, яка набирає обертів в обговоренні CSS, в основному в проекті EQCSS і його копіях. Елементні запити схожі на @media запити з синтаксису, за винятком того, що елементні запити працюють з певними елементами.

    @element {selector} and {condition} [ and {condition} ]* { {css} }

    {selector} – CSS селектор, спрямований на один або більше елементів. Приклад — #id або .class

    {condition} – складається з вимірювання і значення

    {css} – може містити будь-які валідні CSS правила. Приклад #id div { color: red }

    Елементні запити дозволяють стилізувати елементи за умовами min-width, max-width, min-height, max-height, min-characters, max-s min-children, max-children, min-lines, max-lines, min-scroll-x, max-scoll-x і т. д. (див. http://elementqueries.com/).

    Припиніть використовувати CSS JavaScript у веб-розробці

    Коли-небудь варіація EQCSS з’явиться в існуючої специфікації CSS (схрестімо пальці).

    Але постійте!

    Майже всі (якщо не всі) описане можна вирішити. Співтовариством, змінами в React або в styled-components. Але в чому сенс? CSS вже скрізь підтримується, у нього величезне співтовариство, і він просто працює.

    Суть статті у тому, щоб відвернути читачів від використання CSS і JS або від використання styled-components. У стилізації через styled-components є відмінний приклад використання: покращена платформна підтримка. Не використовуйте його з неправильним причин.

    Так що ж сьогодні?

    Використовувати Shadow DOM v1 (51% підтримки) занадто рано. Використовуйте CSS з системами іменування (рекомендую BEM). Якщо турбуєтеся про колізії з іменами класів (або занадто ліниві, щоб використовувати BEM), використовуйте CSS modules. Якщо розробляєте для React, спробуйте babel-plugin-react-css-modules. Якщо розробляєте для нативного React, візьміть styled-components.