Какие селекторы или правила CSS могут существенно повлиять на производительность внешнего макета / рендеринга в реальном мире?

Стоит ли беспокоиться о производительности рендеринга CSS? Или мы должны просто не беспокоиться об эффективности с CSS и просто сосредоточиться на написании элегантного или поддерживаемого CSS вместо этого?

Этот вопрос призван стать полезным ресурсом для фронт-эндовых разработчиков, на котором части CSS могут реально оказывать существенное влияние на производительность устройства и какие устройства / браузеры или механизмы могут быть затронуты. Это не вопрос о том, как писать элегантный или поддерживаемый CSS, а только о производительности (хотя, надеюсь, то, что написано здесь, может дать более общие статьи о передовой практике).

Существующие доказательства

Google и Mozilla написали руководство по написанию эффективного CSS, а набор правил CSSLint включает в себя:

Избегайте селекторов, которые выглядят как регулярные выражения. Не используйте сложные операторы равенства, чтобы избежать снижения производительности

но ни один из них не предоставляет никаких доказательств (которые я мог бы найти) того воздействия, которое они оказывают.

В статье css-tricks.com об эффективном CSS утверждается (после обрисовки множества рекомендаций по эффективности), что мы должны not .. sacrifice semantics or maintainability for efficient CSS Эти дни.

Совершенство убивает сообщение в блоге предположил, что border-radius а также box-shadow отображаются на несколько порядков медленнее, чем простые правила CSS. Это было чрезвычайно важно в движке Opera, но незначительно в Webkit. Кроме того, в тесте CSS, который был опубликован в потрясающем журнале, обнаружено, что время рендеринга для правил отображения CSS3 было незначительным и значительно быстрее, чем рендеринг эквивалентного эффекта с использованием изображений.

Знайте, что ваш мобильный тестировал различные мобильные браузеры и обнаружил, что все они воспроизводили CSS3 одинаково незначительно быстро (за 12 мс), но похоже, что они проводили тесты на ПК, поэтому мы не можем сделать вывод о том, как портативные устройства работают с CSS3 в генеральный.

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

Фон

http://brightgreenscotland.org/wp-content/uploads/2010/09/stand-back-Im-going-to-try-science.png

Я предложил награду за этот вопрос, чтобы попытаться использовать возможности сообщества SO для создания полезного, хорошо изученного ресурса.

6 ответов

Решение

Первое, что приходит на ум, это то, насколько умный движок рендеринга вы используете?

Это, как ни странно, очень важно, когда ставится под сомнение эффективность рендеринга / выделения CSS. Например, предположим, что первое правило в вашем файле CSS:

.class1 {
    /*make elements with "class1" look fancy*/
}

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

.class1.class2 {
    /*make elements with both "class1" and "class2" look extra fancy*/
}

В нашем примере "базовый движок" можно было бы вернуться к каждому элементу DOM и найти оба класса. Умнее двигатель будет сравнивать n('class1') а также n('class2') где n(str) количество элементов в DOM с классом str и принимает любой минимум; предположим, это class1, затем переходит на все элементы с class1 ищет элементы, которые имеют class2 также.

В любом случае, современные движки умны (намного умнее, чем рассмотренный выше пример), а новые блестящие процессоры могут выполнять миллионы (десятки миллионов) операций в секунду. Маловероятно, что у вас есть миллионы элементов в вашей DOM, поэтому наихудшая производительность для любого выбора (O(n)) все равно не будет так уж плохо.


Обновить:

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

Facebook: ~ 1900 элементов (проверено на моей личной главной странице).
Google: ~ 340 элементов (проверено на главной странице, результатов поиска нет).
Google: ~ 950 элементов (проверено на странице результатов поиска).
Yahoo!: ~ 1400 элементов (проверено на главной странице).
Stackru: ~ 680 элементов (проверено на странице вопроса).
AOL: ~ 1060 элементов (проверено на главной странице).
Википедия: ~ 6000 элементов, 2420 из которых не являются spans или же anchors (Проверено в статье в Википедии о Glee).
Твиттер: ~ 270 элементов (проверено на главной странице).

Подводя итоги, мы получаем в среднем ~1500 элементов. Теперь пришло время провести тестирование. Для каждого теста я генерировал 1500 divs (вложенный в какой-то другой divs для некоторых тестов), каждый с соответствующими атрибутами в зависимости от теста.


Тесты

Стили и элементы генерируются с использованием PHP. Я загрузил PHP, которые я использовал, и создал индекс, чтобы другие могли тестировать локально: маленькая ссылка.


Результаты:

Каждый тест выполняется 5 раз в трех браузерах (сообщается среднее время): Firefox 15.0 (A), Chrome 19.0.1084.1 (B), Internet Explorer 8 (C):

                                                                        A      B      C
1500 class selectors (.classname)                                      35ms   100ms  35ms
1500 class selectors, more specific (div.classname)                    36ms   110ms  37ms
1500 class selectors, even more specific (div div.classname)           40ms   115ms  40ms
1500 id selectors (#id)                                                35ms   99ms   35ms
1500 id selectors, more specific (div#id)                              35ms   105ms  38ms
1500 id selectors, even more specific (div div#id)                     40ms   110ms  39ms
1500 class selectors, with attribute (.class[title="ttl"])             45ms   400ms  2000ms
1500 class selectors, more complex attribute (.class[title~="ttl"])    45ms   1050ms 2200ms

Подобные эксперименты:

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


Суть:

Если вы не заботитесь о том, чтобы сэкономить несколько миллисекунд при рендеринге (1 мс = 0,001 с), не беспокойтесь об этом. С другой стороны, хорошей практикой является избегать использования сложных селекторов для выбора больших подмножеств элементов, поскольку это может иметь некоторые заметные различия (как мы видим из результатов теста выше). Все распространенные CSS-селекторы достаточно быстры в современных браузерах.

Предположим, вы создаете страницу чата и хотите стилизовать все сообщения. Вы знаете, что каждое сообщение находится в div который имеет title и вложен в div с классом .chatpage, Правильно использовать .chatpage div[title] выбирать сообщения, но это также плохая практика с точки зрения эффективности. Проще, более легко обслуживать и эффективнее назначать всем сообщениям класс и выбирать их с помощью этого класса.


Причудливый однострочный вывод:

Все в пределах "да, этот CSS имеет смысл" - это нормально.

Большинство ответов здесь сосредоточены на производительности селектора, как если бы это было единственное, что имеет значение. Я постараюсь охватить некоторые мелочи спрайтов (предупреждение спойлера: они не всегда хорошая идея), производительность и использование определенных свойств CSS.

Прежде чем я получу ответ, позвольте мне убрать IMO: лично я категорически не согласен с заявленной потребностью в "доказательных данных". Это просто делает утверждение о производительности заслуживающим доверия, в то время как на самом деле область механизмов визуализации достаточно разнородна, чтобы сделать любой такой статистический вывод неточным для измерения и непрактичным для принятия или мониторинга.

Поскольку оригинальные результаты быстро устаревают, я бы предпочел, чтобы разработчики интерфейсных приложений имели представление о принципах основ и их относительной ценности по отношению к точкам домкратов, связанных с ремонтопригодностью / удобочитаемостью - в конце концов, преждевременная оптимизация - корень всего зла;)


Начнем с селектора производительности:

Мелкие, предпочтительно одноуровневые, специфические селекторы обрабатываются быстрее. В исходном ответе отсутствуют явные показатели производительности, но остается ключевой момент: во время выполнения HTML-документ анализируется в дереве DOM, содержащем N элементы со средней глубиной D и чем в общей сложности S Правила CSS применяются. Чтобы снизить вычислительную сложность O(N*D*S), вам следует

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

    Общепринято, что * следует избегать выбора, но этот момент следует продолжить. "Нормальный" сброс CSS, на самом деле, соответствует большинству элементов - когда эта страница SO профилируется, сброс отвечает за примерно 1/3 всего времени сопоставления селектора, поэтому вы можете предпочесть normalize.css (тем не менее, это только добавляет до 3,5 мс - точка против преждевременной оптимизации стоит сильно)

  2. Избегайте потомков селекторов, так как они требуют до ~D элементы для повторения. Это в основном влияет на несоответствия подтверждений - например, положительный .container .content Для соответствия может потребоваться только один шаг для элементов в родительско-дочерних отношениях, но дерево DOM необходимо будет пройти до самого html прежде чем отрицательный матч может быть подтвержден.

  3. Минимизируйте количество элементов DOM, так как их стили применяются индивидуально (стоит отметить, что это компенсируется логикой браузера, такой как ссылочное кэширование и переработка стилей из идентичных элементов - например, при стилизации идентичных элементов одного уровня)

  4. Удалите неиспользуемые правила, поскольку браузер должен будет оценить их применимость для каждого отображаемого элемента. Достаточно сказать - самое быстрое правило - это то, чего там нет:)

Это приведет к количественным (но, в зависимости от страницы, не обязательно воспринимаемым) улучшениям с точки зрения производительности механизма рендеринга, однако всегда есть дополнительные факторы, такие как издержки трафика и анализ DOM и т. Д.


Далее, CSS3 свойства производительности:

CSS3 принес нам (среди прочего) закругленные углы, градиенты фона и вариации теней, а вместе с ними и множество проблем. Подумайте об этом, по определению предварительно отрендеренное изображение работает лучше, чем набор правил CSS3, которые должны быть отрисованы в первую очередь. Из вики Webkit:

Градиенты, тени и другие декорации в CSS должны использоваться только при необходимости (например, когда форма является динамической в ​​зависимости от содержимого), в противном случае статические изображения всегда быстрее.

Если это не так уж и плохо, возможно, придется пересчитывать градиенты и т. Д. При каждом событии перекраски / перекомпоновки (более подробная информация приведена ниже). Имейте это в виду, пока большинство пользователей не смогут просматривать страницы с большим количеством CSS3 без заметной задержки.


Далее спрайтинг производительности:

Избегайте высоких и широких спрайтов, даже если их трафик относительно невелик. Обычно забывают, что механизм рендеринга не может работать с gif/jpg/png, и во время выполнения все графические ресурсы работают с несжатыми растровыми изображениями. По крайней мере, это легко вычислить: ширина этого спрайта, умноженная на высоту, умноженную на четыре байта на пиксель (RGBA), равна 238*1073*4≅1MB, Используйте его на нескольких элементах на разных одновременно открытых вкладках, и это быстро дает значительную ценность.

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

Альтернативой для рассмотрения являются отдельные изображения в кодировке base64, встроенные непосредственно в CSS.


Далее перекомпоновка и перекраска:

Это ошибочное мнение, что перекомпоновка может быть инициирована только с помощью манипуляции с JS DOM - фактически любое применение стиля, влияющего на компоновку, может инициировать его воздействие на целевой элемент, его дочерние элементы и элементы, следующие за ним и т. Д. Единственный способ предотвратить ненужные итерации это попытаться избежать рендеринга зависимостей. Простым примером этого будет рендеринг таблиц:

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


Я внесу изменения, если вспомню что-то важное, что было упущено. Некоторые ссылки, чтобы закончить с:

http://perfectionkills.com/profiling-css-for-fun-and-profit-optimization-notes/

http://jacwright.com/476/runtime-performance-with-css3-vs-images/

https://developers.google.com/speed/docs/best-practices/payload

https://trac.webkit.org/wiki/QtWebKitGraphics

https://blog.mozilla.org/webdev/2009/06/22/use-sprites-wisely/

http://dev.opera.com/articles/view/efficient-javascript/

Хотя это правда, что

компьютеры были намного медленнее 10 лет назад.

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

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

В продолжение этого я не смог найти конкретную информацию, касающуюся более современных браузеров или мобильных устройств, борющихся с неэффективными селекторами CSS, но я смог найти следующее:

  1. http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/

    Довольно устаревший (IE8, Chrome 2) сейчас, но прилично пытается установить эффективность различных селекторов в некоторых браузерах, а также пытается количественно определить, как # CSS правил влияет на время рендеринга страницы.

  2. http://www.thebrightlines.com/2010/07/28/css-performance-who-cares/

    Снова довольно устарел (IE8, Chrome 6), но доходит до крайности в неэффективных селекторах CSS * * * * * * * * * { background: #ff1; } установить снижение производительности.

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

В этом случае отсутствие доказательств является доказательством отсутствия проблем. Поэтому используйте семантическую разметку (особенно OOCSS) и сообщайте о любых замедлениях, которые вы обнаружите при использовании стандартных селекторов CSS в неясных браузерах.

Люди из будущего: проблемы с производительностью CSS в 2012 году были уже в прошлом.

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

Поскольку я прокомментировал использование PageSpeed ​​для Chrome, это инструмент Google, который анализирует веб-сайт по 27 параметрам, CSS - 1 из них.

Мое сообщение просто касается точно, скорее всего около 99% веб-пользователей смогут открыть веб-сайт и увидеть его правильно, даже люди с IE7 и тому подобное. Чем закрыть около 10% с помощью css3, (если окажется, что вы можете получить дополнительные 1-10 мс на производительность).

Большинство людей имеют по крайней мере 1 Мбит /512 Кбит или выше, и если вы загружаете тяжелый сайт, загрузка занимает около 3 секунд, но вы можете сэкономить 10 мс, возможно, на CSS??

А когда речь идет о мобильных устройствах, вам следует создавать сайты только для мобильных устройств, поэтому, когда у вас есть устройство с размером экрана меньше "Width"px, у вас есть отдельный сайт.

Пожалуйста, прокомментируйте ниже это моя точка зрения и мой личный опыт веб-разработки

Хотя это не связано напрямую с кодом, используя <link> над @import включение ваших таблиц стилей обеспечивает гораздо более высокую производительность.

"Не используйте @import" через stevesouders.com

Статья содержит множество примеров скоростных тестов для каждого типа, а также для включения одного типа в другой (например, файл CSS, вызываемый через <link> также содержит @import в другой файл CSS).

Другие вопросы по тегам