Россия, Сочи, РГПУ им. А.И.Герцена, 1997 |
CSS-оптимизация
Все так просто? Нет, еще проще
А еще можно использовать свойства currentStyle (доступное для чтения) и runtimeStyle (доступное для записи), чтобы переопределять само стилевое свойство при его объявлении (звучит несколько сложно, не так ли?). На самом деле все чрезвычайно просто. Применительно к нашему примеру мы должны будем написать:
#myDiv { border: 10px solid Red; width: expression(runtimeStyle.width = (ieBox ? '100px' : '80px')); }
Например, можно дописать исправление всплывания alt вместо title для картинок:
img { behavior: expression( (alt&&!title) ? title = '' : '', runtimeStyle.behavior = 'none' ) }
Или прозрачность через фильтр:
.button1 { opacity: .1 } .button2 { opacity: .2 } .button3 { opacity: .3 } .button4 { opacity: .4 } .button1, .button2, .button3, .button4 { filter: expression( runtimeStyle.filter = 'alpha(opacity='+currentStyle.opacity*100+')' ) }
Таким образом, наше выражение быстро применяется при загрузке страницы и последующем создании новых узлов скриптом. Такой способ оптимизации подходит только для "статичных" элементов, которым не нужно менять свое отображение динамически. Изменение родительского класса, равнение по высоте окна и эмуляция position: static — все это проблемные участки оптимизации. Лучше их не оптимизировать, а использовать пореже.
Еще одним проблемным местом, на мой взгляд, является общее выполнение скриптов при onresize. Ну и еще серьезный совет: используйте CSS-выражения по минимуму. Лучше всего будет, если они вообще не встретятся у нас на сайте.
Что лучше: id или class?
Далее давайте рассмотрим, как использование id или class влияет на скорость отображения страницы в браузере (сейчас речь не идет о множественном использовании одинаковых id — это и так запрещено спецификацией). Если элемент на странице встречается единственный раз (например, "шапка" или "подвал"), то мы можем с равным успехом использовать id и class для его стилизации.
Методика. Размер файлов
Естественно, что скорость работы одиночного CSS-правила весьма высока, и даже десятки и сотни их не должны заметно замедлить работу браузеров. Поэтому нужно изучать работу нескольких тысяч правил, иначе точность результатов будет весьма невысока. Использовать JavaScript для генерации HTML/CSS-кода не представляется разумным, ибо тогда придется учитывать еще и скорость работы JavaScript-движка в браузерах, и в итоге эксперимент будет недостаточно чистым.
В результате проведенного исследования были сгенерированы статичные файлы (порядка 300 Кб каждый), которые содержали достаточное число различных CSS-селекторов. Это "достаточное" число подбиралось по нескольким параметрам, в том числе таким как размер файла и скорость работы HTML/CSS-кода в браузерах (она должна быть достаточно низкой, чтобы файлы в несколько сотен Кб уже заметно тормозили при открытии).
Итоговые файлы содержали по 4096 объявлений различных CSS-классов (или различных идентификаторов), HTML-код содержал соответствующее количество блоков, у каждого свой индивидуальный класс (или идентификатор). Дополнительно проверялась скорость работы с простым наследованием узлов ( div p, CSS1) и селектор для выбора потомка первого уровня ( div>p, CSS2).
Время открытия страницы
При тестировании браузеров нужно было, во-первых, открыть на клиенте соответствующую данному случаю страницу, а также как-то отследить время на отображение конкретно HTML/CSS-части (понятно, что оно не совпадает со временем открытия всей страницы, которое еще содержит некоторые дополнительные задержки).
Для этого была использована простая техника: перед объявлением CSS-блока запоминается текущая метка времени, а после окончания HTML-блока, который должен отобразиться, запомненная метка вычитается из текущей. Таким образом, мы получаем (в идеале) время на отработку данных CSS-правил и кода, который ими описывается, на клиенте (плюс, возможно, еще какие-то более-менее постоянные расходы, которые нивелируются, если брать относительный, а не абсолютный выигрыш).
Конечно, каждую тестовую страницу можно было подгружать в невидимом iframe или даже AJAX-запросом. Но ведь мы хотим узнать, фактически, скорость рендеринга браузером CSS-правил и соответствующего кода, а это время будет расходоваться только при отображении страницы в окне браузера. Поэтому подгружаемую страницу нужно отображать на экране (по возможности, максимального размера), чтобы отследить имеющуюся разницу.
Результаты
Ниже приведена большая таблица с результатами тестов, которые заключаются в среднем времени отображения страницы для различных вариаций селекторов и разных браузеров. Выделено время, меньшее по сравнению с аналогом. Хочется подчеркнуть, что имеет смысл только относительное ускорение использования одних типов селекторов относительно других в пределах одного браузера. Все времена даны в миллисекундах.
Сравнивать абсолютные значения в рамках данного эксперимента не представляется возможным, ибо каждому браузеру дополнительно нужно было расположить на странице несколько тысяч "плавающих" блоков с заданными размерами ( float:left; width:20px; height:20px, фон для которых и задавался). Эта задача не имеет ничего общего со скоростью работы CSS-селекторов, но может отнимать существенное время у браузера на подготовку изображения страницы на экране (как видно, например, для Opera).
Firefox 2 | Opera 9.5 | Safari 3 | IE 7 | IE 6 | IE 5.5 | |
---|---|---|---|---|---|---|
p.class | 308 | 5887 | 237 | 82 | 72 | 145 |
.class | 219 | 6456 | 225 | 78 | 70 | 149 |
p#id | 349 | 7377 | 338 | 91 | 87 | 156 |
#id | 214 | 7427 | 220 | 83 | 84 | 159 |
div>p.class | 519 | 9412 | 247 | 97 | 84 | 158 |
div>.class | 836 | 12886 | 257 | 95 | 81 | 159 |
div>p#id | 549 | 10299 | 247 | 105 | 92 | 172 |
div>#id | 858 | 15172 | 242 | 113 | 91 | 169 |
divp.class | 827 | 10706 | 256 | 97 | 84 | 161 |
div.class | 505 | 15864 | 247 | 95 | 86 | 160 |
div p#id | 772 | 11952 | 247 | 108 | 99 | 177 |
div#id | 948 | 13306 | 255 | 108 | 95 | 173 |
div.div p.class | 1001 | 10519 | 263 | 111 | 94 | 165 |
div.div .class | 1099 | 18742 | 253 | 105 | 92 | 166 |
div.div p#id | 1161 | 10989 | 266 | 117 | 95 | 181 |
div.div #id | 1247 | 15816 | 256 | 114 | 100 | 187 |