Упрощаем CSS-селекторы. Оптимизация CSS-структуры. Оптимизация структуры веб-страниц
@import @import
link @import
link с @import
Блоки link с @import
Много @import
link link
Упрощаем CSS-селекторы
Для большинства сайтов возможный выигрыш в производительности после оптимизации CSS-селекторов будет крайне незначительным и не будет стоить потраченного времени. Есть несколько типов CSS-правил (например, expression для IE) и взаимодействий с JavaScript, которые могут существенно замедлить страницу. Именно на них и нужно концентировать усилия.
Большая часть информации о быстродействии CSS-селекторов ожжет быть получена из статьи David Hyatt Пишем эффективный CSS для интерфейсов в Mozilla (https://developer.mozilla.org/en/Writing_Efficient_CSS ). Стоит привести оттуда одну цитату:
Система стилей находит элемент, соответствующий CSS-правилу, начиная с правого конца селектора и двигаясь налево. Пока мы еще находим элементы, соответствующие селектору, мы продолжаем двигаться. Остановка возможна только в случае нахождения элемента, соответствующего всему CSS-селектору, или невозможность такой элемент найти для какой-то части селектора.
Не очень понятно, как устроен движок CSS-селекторов в других браузерах, например, в IE (а если принять во внимание тесты CSS-производительности из книги «Разгони свой сайт», то возникает предположение, что в Opera движок разбора CSS-селекторов работает как раз слева направо). Может быть, он использует комбинированный подход: как справа налево, так и слева направо. Переключение может происходить по какому-то признаку (например, по наличию #id).
Однако по заявлению Виталия Харисова, руководителя группы HTML-верстки в Яндексе, тесты показывают (http://clubs.ya.ru/yacf/replies.xml?item_no=338&ncrnd=3604 ), что все браузеры применяют селекторы одинаково, справа налево.
Благодаря вышесказанному мы можем теперь сфокусировать оптимизационные усилия на тех CSS-селекторах, правая часть которых будет соответствовать большому числу элементов на странице. Давайте, рассмотрим для примера DIV DIV DIV P A.class0007 {}. У этого селектора присутствует 5 уровней вложенности потомков, для которых необходимо найти соответствие в DOM-дереве. Это выглядит очень ресурсоемко, однако при взгляде на самую правую часть этого селектора, A.class0007, мы прекрасно понимаем, что ей соответствует только 1 элемент на странице, поэтому браузеру очень легко установить точное соответствие.
Ключевым моментом в оптимизации CSS-селекторов является самая правая часть, часто также называемая «ключевым селектором». Вот пример гораздо более ресурсоемкого селектора: A.class0007 * {}. Хотя он может и выглядеть просто, но для браузера очень тяжело его вычислить. Поскольку браузер будет двигаться справа налево, то он начнет со всех элементов, которые подходят под ключевой селектор (*). Это означает, что браузер попытается проверить все элементы на странице, нужно ли к ним применить этот стиль.
На следующей диаграмме показана разница во времени тестами для универсального селектора и прошлым тестами для наследственных селекторов.
Рис. 5.8. Разница во времени загрузки (в мс) для универсального селектора. Истоник: stevesouders.com
Очевидно, что CSS-селекторы с ключевым элементом, который соответствует большому числу узлов, будут вычисляться существенно дольше и заметно тормозить загрузку страницы. В качестве других примеров селекторов, которые могут привести к большим вычислениям со стороны браузера, можно отнести:
A.class0007 DIV {}
#id0007 > A {}
.class0007 [href] {}
DIV:first-child {}
Не все CSS-селекторы существенно влияют на производительность, даже те, которые могут выглядеть сложно. При оптимизации стоит фокусироваться на устранении CSS-правил с ключевым селектором, соответствующим большому числу элементов. Это становится особенно важно для Веб2.0 приложений с большим числом узлов DOM-дерева, огромным количеством CSS-правил и отрисовок страниц.
Некоторой проблемой является то, что почти все известные JavaScript-библиотеки разбирают селекторы слева направо. Тем самым, мы должны писать 2 вида селекторов: оптимизированных под браузеры и оптимизированных под JavaScript-библитеки. На данный момент только немногие поддерживают нотацию справа налево, например, CSS1-ветка YASS (http://yass.webo.in/ ).