Дебаты на тему «А нужен ли нам вообще CSS?»

Перевод статьи The Debate Around «Do We Even Need CSS Anymore?» с сайта css-tricks.com, автор — Крис Койер.

С недавних пор об этом много спорят. Это обсуждалось на нескольких конференциях и митапах, где я недавно присутствовал. Я видел презентации об этом. Я знаю людей, выпускающих проекты без единой строчки CSS. Дико, да?

Думаю, мы могли бы посидеть у костерка и поговорить об этом предельно рационально, не упуская ничего важного.

Возможность стилизовать нам нужна в любом случае

Никто не говорит, будто нам не нужны стили. Нам всё еще нужно что-то стилизовать, вопрос в том, где и как это делать. На днях я был на BrooklynJS, и Джед Шмидт сказал:

Худшее, что есть в CSS — это «Cascading» («каскадные») и «Sheets» (одно из значений этого слова — «простыни»)

За что все не любят CSS?

Вот основные аргументы против CSS:

  • Всё глобально. Селекторы сверяются со всем подряд в DOM. Чтобы отстоять эффективность в борьбе с этим, нужны стратегии именования (которые непросто поддерживать, зато легко нарушить).
  • CSS растёт со временем. Даже специалисты из больших команд признают, что боятся собственного CSS. Нельзя просто удалить что-либо, поскольку трудно узнать наверняка, безопасно ли это. Вот они и не удаляют, лишь добавляют. Я видел график размера реального CSS за пять лет, на котором он неуклонно рос, хотя компания уделяла много внимания производительности.
  • Если стили описываются в языке программирования, то с ними проще работать динамически. Аргумент примерно такой: «мы и так уже «оживили» CSS препроцессорами, почему бы не выйти на следующий уровень?». Например, можно задавать разные стили в зависимости от строки User-Agent (если вам нужен действительно спорный пример) или от текущей ширины модуля.

Какова же альтернатива CSS?

Альтернатива — встроенные стили. Так, вместо

<div class="module">

У нас получится

div style="padding: 20px; background: #eee; margin: 0 0 20px 0;">

Никто на моей памяти еще не утверждал, будто эти стили нужно вставлять прямо в HTML, который вы пишете. Смысл в том, чтобы применять стили к элементам с помощью JavaScript.

React воплощает многие из этих идей

React — JavaScript-библиотека, которая помогает с проблемами по визуальной части на сайте. Эту крайне популярную и набирающую обороты библиотеку разрабатывает в основном Facebook. Недавно по ней прошла конференция, и из неё вот-вот получится фреймворк для построения нативных приложений.

Одно из его центральных понятий— «Виртуальная DOM». Вы строите HTML, который планируете использовать, прямо в JavaScript. Довольно странно на первый взгляд, но HTML и JavaScript всегда тесно связаны, и поэтому напрашивается с самого начала писать их вместе. Недавно я цитировал Кита Джей Гранта и сделаю это снова:

Эта взаимосвязь реальна и неизбежна. Нам так или иначе нужно привязывать обработчики событий к элементам на странице. Нам всё равно нужно обновлять элементы на странице из JavaScript. Наш код должен взаимодействовать с DOM-элементами в реальном времени, и это взаимодействие должно быть двусторонним.

…мантра React — перестать делать вид, будто DOM и управляющий ей JavaScript существуют отдельно друг от друга.

Управление встроенными стилями — стандартная возможность React. Они там прямо так и называются: встроенные стили. Вот базовый пример:

See the Pen Inline Styles with React by Максим (@psywalker) on CodePen.

Затея с виртуальной DOM, которую строит React, важна также из-за ее скорости. Любые манипуляции с DOM в JavaScript обычно считаются медленными, поэтому управление стилями путём манипуляций с DOM — тоже. Но у React есть волшебный порошок, ускоряющий манипуляции, так что при работе с этой библиотекой можно не беспокоиться о «тормозах».

Вот ещё один пример Криса Нагера.

Стили по-прежнему пишутся отдельно

CSS отделяет стили от всего остального. Просто файлы, с которыми вы работаете, управляя стилями. Вряд ли вы откажетесь от этого, перенеся установку инлайн-стилей в Javascript. Ну был бы у вас, может, не styles.css, а styles.js. Вы всё равно будете писать пары ключ/значение и собирать файлы в один сжатый.

Несколько иначе, но работа со стилями по-прежнему идет отдельно

Что вам даст встраивание стилей?

Нет каскада

Страшная «глобальность» CSS обезвреживается. Каскад сужается. Едва ли можно сказать, что каскада совсем не осталось, ведь некоторые стили наследуются, так что стили по-прежнему могут передаваться дочерним элементам и это одно из определений каскада. Но благодаря «как бы модульной» природе такого стиля разработки проблем из-за перекрытия стилей наверняка станет меньше. У этого модуля стили вот такие, у того — вот сякие: откуда конфликтам взяться?

Всё на JavaScript

У меня такое чувство, что многим просто больше нравится делать всё на JavaScript. Безусловно, часть успеха Node.js можно приписать этому факту.

Динамические стили

«Состояние» — прерогатива JavaScript. Если вам хочется/нужно изменить стили в зависимости от динамических условий (состояний) на сайте, возможно, имеет смысл манипулировать оформлением, привязанным к состоянию, вместе со всем остальным.

В недавнем докладе на CSS Conf (слайды), Колин Мегилл привел новое текстовое поле для ввода твита в Твиттере как пример динамической области, меняющей состояние других элементов.

state-changes

Кто реально использует это?

Я слышал утверждение Колина Мегилла, что они выпускают «что-то большое», в котором буквально нет ни байта CSS, и у них нет проблем с производительностью. Я добавлю сюда ссылки, если сам их узнаю. Говорят, что какой-то большой проект будет запущен в течение месяца.

Я знаю, что Джед Шмидт работает над мобильной версией UNIQLO, и там можно увидеть встроенные стили в действии:

inline-styles-on-uniqlo

Уточнение от Джеда. Эта версия сайта полностью написана на Sass, а видимые на ней встроенные стили — от JavaScript-анимаций.

Кристофер Чидо тоже говорит об этом, а он — вообще-то разработчик Facebook, так что, может быть, и Facebook тоже?

Нельзя ли объединить эту идею… в общем, с CSS?

Даже если вы готовы принять идею встроенных стилей, не сможет ли она ужиться с какой-то частью (можно ли обойтись без этого уточнения) обычного CSS? Годятся ли встроенные стили для раскладки страницы? Не стоит ли оставить глобальными базовые настройки типографики? Пожалуй, у нас здесь еще непаханное поле для экспериментов, прежде чем можно будет говорить о каком-то лучшем подходе.

У m.uniqlo.com, приведенного как пример выше, используется также 57-килобайтный CSS-файл, а в DOM можно найти примеры классов, зависящих от состояния (напр. «is-open»).

Многим это весьма не нравится

Сюрприз! Аргументов против подобных вещей больше, чем аргументов за. Когда я собирал мнения об этом, то сказал Лии Веру «Некоторым действительно нравится это!», на что она ответила:

В мире можно найти людей, которым нравится питаться экскрементами, но это не значит, что это хорошая идея.

Пробежимся по другим аргументам:

Оформление — это то, для чего CSS предназначен

Это «религиозная» позиция, с которой мы вряд ли придем к чему-то путному.

Разделение ответственности лежит в основе CSS

Разделение ответственности — очень полезный принцип при создании таких сложных штук, как сайты. Когда вы пишете CSS, вы реализуете этот принцип автоматически: этот файл отвечает только за оформление.

У встроенных стилей наивысшая специфичность

Минимизация специфичности в CSS означает, что если вам придется переопределить что-то в оформлении, вы всегда сможете использовать ее как инструмент. Когда специфичность уже на максимуме, такой роскоши, как пространство для манёвра, у вас нет.

Да, определенное свойство/значение во встроенном стиле еще можно перекрыть с помощью объявления !important, но это немного другое понятие, а если понадобится переопределить и его, будет вообще жуть.

Некоторые простые состояния намного проще реализуются на CSS

Как сделать :hover/:focus/:active во встроенных стилях? А никак. Можно только имитировать. А что насчёт медиа-запросов?

Добавление/удаление классов — уже идеальный инструмент для смены состояний

JavaScript действительно здорово справляется с добавлением/удалением классов у элементов. А классы — идеальный способ работать с состояниями в CSS

.is-open {
  display: block;
}

Кроме того, можно менять состояние родительских элементов (меняя класс), чтобы повлиять на состояние множества элементов внутри:

.tweet-too-long {
  .tweet-button {
    opacity: 0.5;
  }
  .warning-message {
    display: inline-block;
  }
}

Браузеры не рассчитаны на такой способ стилизации

Например, встроенные стили — это фактически данные, хранящиеся в атрибуте непосредственно у DOM-элемента. Вес DOM — это серьезно (из-за него браузер может «тормозить», а то и «упасть»). Но эта стилевая информация хранится не только в атрибуте style, она еще и представлена в DOM в свойствах стиля элемента. Это одно и то же, или такая стилизация создает некую двойную нагрузку?

Есть ли разница в скорости между…

var thing = document.getElementById("thing");
thing.style.width = "100px";
thing.style.height = "100px";
thing.style.backgroundColor = "red";

var thing2 = document.getElementById("thing-2");
thing2.setAttribute("style", "width: 100px; height: 100px; background-color: red;");

И вот как узнать, что из этого лучше для всех браузеров? Если подобное «взлетит», придется ли браузерам менять свой подход к обработке таких вещей?

У браузеров есть целое отдельное понятие CSSOM. Нельзя ли использовать его в JavaScript как-нибудь разумнее, чем через встроенные стили?

Причина успеха CSS — простота

Порог вхождения в CSS весьма невысок. Многие его знают. Легко найти специалиста по нему. Его можно переносить из проекта в проект и от разработчика к разработчику.

Некоторые из «динамических» стилевых проблем решаются обычным CSS

  • Некоторые демо-примеры включают измерение ширины и вычитание из нее фиксированных значений. CSS позволяет делать это с помощью calc().
  • Некоторые демо-примеры включают установку font-size или line-height в зависимости от ширины или высоты браузера. В CSS это возможно с единицами измерения vh, vw и т.п. Использовать для подобного JavaScript — это перебор.
  • Есть демо-примеры, динамически меняющие цвет многих разных элементов. В CSS это будет возможно при помощи «родных» CSS-переменных.

Мы пробовали это в 1996 г., и тогда это была неудачная идея

Прочь с моей лужайки.

CSS может кешироваться

Сеть — всё еще узкое место. CSS-файлы могут кешироваться, так что сеть вообще не играет роли, и всё просто «летает».

Вам никто не мешает использовать React

React — просто чудо. Вот статья Дэвида Хуршида про оформление компонентов React с помощью Sass. Марку Далглешу не нравится глобальная природа CSS, и у него есть рабочие идеи по локализации селекторов. Глен Мадден подробно рассказывает об этом в статье «Совместимый CSS»

Думает ли хоть кто-нибудь о прогрессивном улучшении?

Это более глобальный вопрос, возможно, выходящий за рамки статьи. Поскольку сайты (в т.ч. сайты на основе React, использующие встроенные стили) могут полностью генерироваться на стороне сервера, это значит, что их можно создавать с мыслью о прогрессивном улучшении. Хотя «можно» и «поощряется на деле» — далеко не одно и то же.

P.S. Это тоже может быть интересно:

11 Комментарии

  1. Антон

    Переводил Промпт?

    1. Максим Усачев (Автор записи)

      Прошу прощения, здесь чисто моя вина, перевод мой (да, смело можно назвать меня Промптом, ибо мне ещё есть куда расти). При вычитывании статьи забыл почистить кое-какие моменты. Вроде всё исправил, в следующий раз буду внимательнее!

      Если у вас есть какие-то замечания, пожалуйста напишите мне на почту (psywalker09@gmail.com), обязательно обращу внимание и приму меры.

      1. Антон

        В оригинале статья хорошая, а перевод просто плохой. Каждое второе предложение просто не по-русски написано — переведено в лоб, без мысли о том что стиль автора в общем так себе и не стоило его пытаться сохранять.

        1. Максим Усачев (Автор записи)

          На счёт «каждое второе предложение» всё-таки не соглашусь, но в целом сложные моменты в переводе были, не могу отрицать. Сегодня уже поздно, но завтра с коллегой мы обязательно всё ещё раз вычитаем и примем меры!

        2. Максим Усачев (Автор записи)

          Антон, всю статью перелопатили, теперь приятно смотреть, можете убедиться в этом сами. Прошлый «кальковатый» вариант вроде бы исчез. Ещё раз прошу прощения, в следующий раз буду внимательнее и дотошнее относиться к переводам!

  2. AntonMMF

    «За что все не любят CSS?»

    В первых двух случаях автору надо рассказать про БЭМ, его использование решает проблемы с глобальностью и удалением лишнего CSS. И нет правила, что нужно чётко его использовать под себя, как больше нравится, так его и модифицируй под себя.

    Если автор настолько не в состоянии постичь азы именования классов и написания CSS по какой-то методологии, причём настолько, что предлагает писать стили в JavaScript, то это заставляет задуматься о компетентности автора в области вёрстки.

    А теперь о предложенном авторе решении.

    1. Первую проблему автор своим решением не решает абсолютно. Вот ни разу оно не решается, если попытаться это применять.

    Вот есть строка
    h2 span { color: red }
    а вот у нас это же на JS
    document.getElementByTagName(«h2 span»).setAttribute(«style», «color: red;»);

    Где тут решается проблема с глобальностью стилей? Я не вижу. И не надо говорить про использование классов, классы всё и в CSS решают, городить JS ради такого не стоит.

    2. «CSS растёт со временем». А JS расти не будет?
    Точно также будут огороды JS, в котором через 5 лет «так-с, а это что у нас такое и зачем оно тут нужно?».

    3. Третья проблема конечно же решается только через JS, но можно просто вписать, например в html-тег, какой-то класс, определённый на JS, и уже в CSS плясать от этого класса.

    1. SelenIT

      1. Насколько я понял Криса, он имеет в виду не навешивание скриптом стилей на кучу элементов (что, естественно, ничем не лучше CSS, только хуже:), а описание стилей генерируемых компонентов в самих компонентах: один компонент/модуль — один стиль — одно место описания. Напр. вставляет скрипт соцкнопочки — этот же скрипт их и стилизует, тут же, не отходя от кассы.

      БЭМ без сопутствующего стека средств автоматизации — лишь одна из стратегий именования, которые Крис упоминает как средство решения проблемы глобальности каскада в рамках одного CSS, со всеми минусами. А с полным стеком — просто другая технология, которая не всем подходит (особенно если проект был начат без нее).

      2. JS всё-таки позволяет минимально ограничивать «неймспейсы» для стилей рамками модуля. Удалили из проекта модуль — можно смело грохать его стили. В CSS это труднее из-за неявных глобальных зависимостей.

      3. Да, это действительно выглядит лучшим решением, и Крис упоминает об этом ближе к концу статьи.

      Не спорю, что тон статьи несколько провокационный, она и задумана скорее как затравка для дискуссии, чем как реклама конкретного решения. Но проблема реально существует, язык стилей для текстовых документов действительно не лучшим образом подходит для оформления интерфейсов, и что-то с этим делать надо. Конечно, есть надежда, что в скором светлом будущем сам CSS обзаведется лучшими средствами для решения этой задачи (напр. CSS Scoping), но пока решать ее приходится сейчас и тем, что есть. И просто осмотреться по сторонам в поисках альтернатив, как предлагает статья Криса, имхо, всё-таки полезно — хотя бы даже для того, чтобы убедиться, что альтернативы только хуже..:)

  3. sasha

    Извините, не по теме. Читаю с андроида. Посты с ответами очень узкие. Например от Максима Усачева 12.39 текст в столбик по одному слову.

    1. SelenIT

      Спасибо за багрепорт! Вообще текущий дизайн сайта рассматривался как временный/переходный, поэтому подобные вещи могут быть недотестированы. Но в любом случае в ближайшее время исправим!

      1. Иван

        Извините, я тоже не по теме, ссылку на обратную связь не нашёл, а приведёная выше почта могла устареть. Читаю с нетбука с разрешением 1024х600. Верхний баннер не влазит по ширине, поэтому отображается в две строки. При этом его высота увеличивается в два раза. Всё бы ничего, но, наверное для нашего удобства, он прибит гвоздями к верхней части окна и загораживает пятую или шестую часть страницы, что при высоте дисплея в 600 пикселов очень неприятно.
        И при любой высоте дисплея это мешает листать страницу постранично клавишами «пробел» или «Page Down», т. к. часть непрочитаного текста уползает под баннер. Приходится листать стрелкой вниз построчно, что очень напрягает. Если эту навигацию надо непремено делать неподвижной, то возможно сбоку на альбомно-ориентированном дисплее она бы мне меньше мешала.

        1. SelenIT

          Спасибо за замечание! В ближайшее время что-нибудь придумаем. В качестве временной меры пока подвинул границу Media Query, чтобы на ширине 1024 была планшетная версия, где меню компактнее.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.