Лайфхак,  Новости,  Ожидание vs Реальность,  Разработка

Оптимизация CSS: ID-селекторы и другие мифы

Оптимизация CSS

Типичный сайт сегодня насчитывает около 500 КБ сжатого JavaScript и 1.5 Мб изображений, загружаемых 400 миллисекунд на среднем Android-устройства с помощью 3G. Несмотря на это, продолжительность обработки CSS — самая маленькая из неудобств.

Тем не менее, рассмотрим вопрос оптимизации CSS подробнее чтобы удалить все мифы и предубеждения.

Основы обработки CSS

В статье мы не будем подробно рассматривать особенности функционирования СSS-значений и свойств, зато остановимся на производительности самых селекторов. В статье ссылаться на двигатель Blink, в частности на Chrome 62.

Cелектор можно условно разбить на несколько групп и примерно отсортировать от наименее до наиболее производительного.

Место Тип пример
1. ID #classID
2. класс .class
3. Tег div
4. Обобщенный и соседский селекторы div ~ a, div + a
5. Дочерний селектор и потомок div > a, div a
6. универсальные стиле *
7. атрибуты [type="text"]
8. Псевдоклассы и элементы a:first-of-type, a:hover

Значит ли это, что следует использовать только ID и классы? Не совсем. Сначала рассмотрим как браузеры интерпретируют CSS-селекторы.

Считывания CSS-селектора браузером происходит справа налево. В составленных селекторах находящийся правее, называется еще ключевым селектором . Например, в селекторе #id .class > ul aключевым селектором является а. Браузер сопоставляет сначала все ключевые селекторы. Таким образом, он находит на странице все элементы, соответствующие селектору а, затем находит все ulэлементы и фильтрует элементы а— потомки ul. Этот процесс продолжается пока не достигнуто крайнего левого селектора.

Поэтому чем короче селектор, тем лучше. Старайтесь организовывать ключевые селекторы как классы или ID, чтобы достичь максимальной скорости и конкретности.

Замер производительности

В серии тестов , созданной еще в 2014 году, выполняется замер эффективности селекторов. Тест заключался в измерении скорости на обработку около 1000 селекторов в DOM, начиная от идентификаторов к достаточно серьезным и длинных сложенных селекторов. Выяснилось, что разница между быстрым и медленным составляла около 15мс.

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

В своем испытании я использовал тест Пола Левиса, который обеспокоен по поводу «количественных селекторов» :

Такие селекторы медленные из всех возможных. Примерно в 500 раз медленнее, чем что-то странное, вроде div.box:not(:empty):last-of-type .title.

В тесте было привлечено более 50 000 элементов. Были получены следующие результаты ( можно проверить самостоятельно ):

селектор Продолжительность запроса (мс)
div 4.8740
.box 3.625
.box > .title 4.4587
.box .title 4.5161
.box ~ .box 4.7082
.box + .box 4.6611
.box:last-of-type 3.944
.box:nth-of-type(2n - 1) 16.8491
.box:not(:last-of-type) 5.8947
.box:not(:empty):last-of-type .title 8.0202
.box:nth-last-child(n+6) ~ div 20.8710

Конечно, результаты будут варьироваться в зависимости от использования querySelectorили querySelectorAllи количества соответствующих узлов на странице. Тем не менее, querySelectorAll, ориентированный на все соответствующие элементы, более близкий к практическому применению в CSS.

Даже в тестовом варианте, где происходит поиск и сопоставление примерно 50 0000 элементов, а используются селекторы, вроде последнего в таблице, было обнаружено, что самая медленная продолжительность запроса ~ 20 мс, а быстрая — в случае обычного класса — ~ 3.5 мс. Разница не принципиальна. На практике DOM насчитывает в среднем 1000-5000 узлов, поэтому результат уменьшится примерно в 10 раз, а скорость обработки продлится меньше миллисекунды.

Тест показал, что не стоит беспокоиться о производительности селекторов CSS. Достаточно не переусердствовать с псевдоселекторамы и действительно длинными селекторами.

Мы также видим, как Blink улучшилось за последние два года. Вместо заявленного замедление в 500 раз для «количественного селектора» ( .box:nth-last-child(n+6) ~ div) по сравнению с селектором ( .box:not(:empty):last-of-type .title) можно заметить замедление только в 1.5 раза. Поэтому, можем только надеяться, что браузеры будут еще больше совершенствоваться, уменьшая влияние производительности CSS-селекторов.

Тем не менее, следует применять классы, где это возможно, а также соблюдать определенные правила именования, вроде BEM, SMACSS или OOCSS, потому что это не только повысит производительность сайта, но и сделает ваш код удобным для отладки. Составленные селекторы, особенно те, что применяются с тегом, и универсальные селекторы вроде .header nav ul > li a > .innerвызывают много ошибок. Основная сложность заключается в налаживании такого кода, особенно после предыдущего разработчика.

Количество не означает качество?

Большой проблемой селекторов является их избыток или «раздувание стилей», что встречается довольно часто. Типичными примерами служат сайты, которые импортируют все CSS с фреймворков вроде Bootstrap или Foundation, в то время как используют не более 10% из всех стилей. Другой пример — старые проекты, не испытывали рефакторинга. Их CSS превращается в скорее «Хронологические таблицы стилей» с большим количеством классов, добавлялись в конец файла, когда проект разрастался. Конечно, такой подход не добавляет удобства.

Обратите внимание, что передача и обработка больших CSS-файлов занимает много времени (а передача данных является наиболее узким местом в производительности сайта). Кроме формирования DOM с вашего HTML, браузеру необходимо создать CSSOM (CSS Object Model) для сравнения с DOM и сопоставления селекторов.

Поэтому, применяйте более «чистые» CSS-селекторы, загружайте только то, что вам нужно и, при необходимости, используйте UNCSS .

Для более глубокой информации об обработке CSS браузерами ознакомьтесь: Webkit , Blink , новый CSS двигатель Stylo .

недействительность стилей

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

Обработка CSS — лишь один из многих этапов, которые необходимо пройти для конечного загрузки страницы в браузере. Посмотрим как браузер осуществляет обработку с точки зрения показа страницы (источник: Google).

rendering

Не будем вдаваться в подробности производительности JavaScript и композиции, зато остановимся подробнее на обработке и расположении элементов на странице.

После конструирования DOM и CSSOM браузера необходимо объединить их в дерево визуализации, а уже потом показать на экране. На этом этапе браузера надо определить рассчитан CSS для каждого соответствующего элемента. Можно убедиться в этом самостоятельно на панели Elements> Styles инструментов разработчика. Для создания окончательного рассчитанного CSS для элемента учитываются все соответствующие стили, каскадирование, а также специфические пользовательские настройки в браузере.

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

Наконец, браузер превращает каждый узел в дереве визуализации на фактические пиксели на экране во время воспроизведения.

Что же происходит, когда мы видоизменяем DOM путем замены некоторых классов на странице, добавляем или удаляем узлы, атрибуты, или каким-либо образом трогаем HTML ( или непосредственно таблицы стилей )? Таким образом мы аннулируем рассчитаны стиле, поэтому браузера необходимо аннулировать все дерево, ниже соответствующих селекторов. Ранее, если вы, например, меняли класс элемента body, все элементы-потомки должны были перечислить свои стили.

Одним из способов избежать этой проблемы является сокращение названия селекторов. Вместо использования #nav > .list > li > aпопробуйте что-то вроде .nav-link. Таким образом, область недействительности стиля уменьшится, если вы измените что-нибудь в #nav, то перечисление всего узла не произойдет.

Другой способ решения проблемы — уменьшение количества недействительных элементов. Имейте это в виду особенно при применении анимаций, когда у браузера есть только 10 мс чтобы все обработать.

Для углубления знаний: здесь можно узнать больше о недействительности стилей на примере Blink.

вывод

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

Интересно, что даже Google удалил правило «Использование эффективных CSS-селекторов» с «Советов по скорости страниц» .

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

И напоследок: всегда проводите собственные тестирования. Подробнее информации, которая была в сети несколько лет назад. Тенденции меняются кардинально и с невероятной скоростью. То, что актуально сегодня, устареет раньше, чем вы думаете.

0 голосов (0 баллов в среднем)
1+
Поделиться

Добавить комментарий

Войти с помощью: 

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