20 советов по оптимизации производительности CSS

В этой статье мы рассмотрим 20 приемов оптимизации CSS, которые повысят производительность сайта.

Используйте аналитические инструменты

Используйте инструменты разработчика, встроенные во все наиболее популярные браузеры. Чтобы запустить их, нажмите F12, Ctrl+ Shift+ I или Cmd+ Alt+ I в Safari (macOS).

Наиболее полезные вкладки включают в себя следующие данные:

  • «Сеть»- графики загрузки ресурсов. Для получения достоверных результатов отключите кэш. Ищите файлы, которые загружаются медленно или блокируют загрузку других. Браузер обычно блокирует рендеринг при загрузке и парсинге файлов CSS и JavaScript.
  • «Производительность» - содержит данные о процессах браузера. Начните запись, выполните какое-либо действие (например, перезагрузите страницу), затем остановите запись и просмотрите результаты. Обратите внимание на:
  1. Excessive layout/reflow – действия, при которых браузер вынужден пересчитывать положение и размер элементов страницы.
  2. Expensive paint – затратные действия отрисовки.
  3. Compositing – действия, при которых отрисованные части страницы объединяются для отображения на экране. Это наименее ресурсоемкие процессы.

Браузеры на основе движка Chrome, предоставляют вкладку «Аудит». В ней можно запустить инструмент Google Lighthouse. Он предоставляет рекомендации по производительности CSS.

Онлайн-инструменты

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

В первую очередь выполняйте основные задачи

Код CSS может загружать объемные ресурсы, которые можно оптимизировать. Примеры:

  • Активируйте на сервере HTTP/2 и GZIP-сжатие;
  • Используйте сеть доставки контента (CDN), чтобы увеличить количество одновременных HTTP-соединений.
  • Удалите неиспользуемые файлы.

Изображения являются основной причиной большого объема веб-страниц. Поэтому:

  1. Измените размеры растровых изображений. Только для небольшого количества сайтов требуются изображения шириной более 1600 пикселей.
  2. Используйте правильные форматы файлов. JPG лучше всего подходит для фотографий, SVG – для векторных изображений и PNG – для всего остального.
  3. Уменьшайте размеры файлов с помощью увеличения коэффициентов сжатия.

Замените изображения эффектами CSS

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

Удалите ненужные шрифты

Рекомендации:

  1. Используйте только те шрифты, которые необходимы.
  2. Загружайте только те значения толщины и стили, которые нужны.
  3. Ограничьте наборы символов. Google Fonts позволяет выбирать определенные символы, добавляя значение &text= к URL-адресу шрифта. Например, fonts.googleapis.com/css?family=Open+Sans&text=SitePon для отображения «SitePoint» с помощью Open Sans.
  4. Используйте вариативные шрифты, которые определяют несколько толщин и стилей путем интерполяции, чтобы файлы были меньше.

Избегайте @import

Правило @import позволяет импортировать CSS в другой файл. Например:

/* main.css */
@import url("base.css");
@import url("layout.css");
@import url("carousel.css");

Но правила @import могут быть вложенными, поэтому браузер должен загружать и анализировать каждый файл последовательно.

Несколько тегов <link> в HTML позволяют загружать файлы CSS параллельно. Это более эффективно, особенно при использовании HTTP/2:

<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="layout.css">
<link rel="stylesheet" href="carousel.css">

Конкатенация и минимизация

Большинство инструментов сборки позволяют объединить все компоненты в один большой файл CSS, в котором будут удалены ненужные пробелы, комментарии и символы.

Объединение менее необходимо при использовании протокола HTTP/2 , который объединяет запросы. Но большинство сайтов, скорее всего, выиграют от отправки одного файла, который сразу же кэшируется браузером.

Также GZIP может максимизировать сжатие, когда в файле часто используются повторяющиеся строки.

Используйте современные методы компоновки

Много лет нам приходилось использовать CSS float для верстки страниц. Но существуют более эффективные технологии:

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

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

Уменьшите код CSS

Со временем CSS может раздуться по мере увеличения количества функций. Рекомендации по решению данной проблемы:

  • Откажитесь от использования больших CSS-фреймворков.
  • Организуйте CSS-файлы. Виджет карусели значительно легче удалить,  если его CSS четко определен в widgets/_carousel.css.
  • Используйте методологии именования, такие как BEM, которые помогают в разработке отдельных компонентов.
  • Избегайте использования !important для переопределения каскада.
  • Избегайте использования стилей, встроенных в HTML.

Такие инструменты, как UnCSS, могут помочь удалить избыточный код.

Следуйте каскаду!

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

Упростите селекторы

Упрощение селекторов уменьшит размер CSS-файлов и поможет браузеру быстрее их анализировать. Вам действительно нужен такой селектор ?!

body > main.main > section.first h2:nth-of-type(odd) + p::first-line > a[href$=".pdf"]

Остерегайтесь использования ресурсоемких свойств

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

*, ::before, ::after {
  box-shadow: 5px 5px 5px rgba(0,0,0,0.5);
}

Все свойства, которые требуют перерасчета перед рендерингом страницы, потребляют больше ресурсов:

  • border-radius;
  • box-shadow;
  • opacity;
  • transform;
  • filter;
  • position: fixed.

Применяйте CSS-анимацию

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

Избегайте анимирования ресурсоемких свойств

Анимация размеров или положения элемента может привести к перестройке всей страницы в каждом кадре. Производительность можно улучшить, если анимация будет влиять только на этап компоновки. Более эффективно анимация используется следующими свойствами:

  • opacity; 
  • transform.

Укажите, какие элементы будут анимированы

Свойство will-change позволяет указать, какой элемент будет анимирован. Поэтому браузер может заранее оптимизировать производительность. Например:

.myelement {
  will-change: transform;
}

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

  • используйте will-change только в качестве крайней меры для устранения проблем с производительностью;
  • не применяйте его к большому количеству элементов.

Применяйте SVG-изображения

Масштабируемая векторная графика (SVG) обычно используется для логотипов, диаграмм, иконок и более простой графики. Вместо определения цвета каждого пикселя (как в растровых изображениях JPG и PNG), SVG определяет простые фигуры (линии, прямоугольники и круги). Например:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
  <circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" />
<svg>

Простые SVG меньше по размеру, чем растровые изображения. При этом они могут бесконечно масштабироваться без потери качества.

SVG может быть встроен в CSS-код как фоновое изображение. Что позволяет избежать дополнительных HTTP-запросов. Например:

.mysvgbackground {
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600"><circle cx="400" cy="300" r="50" stroke-width="5" stroke="#f00" fill="#ff0" /></svg>') center center no-repeat;
}

Стилизуйте SVG с помощью CSS

Чаще всего SVG-файлы включаются непосредственно в HTML-документ:

<body>
  <svg class="mysvg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
    <circle cx="400" cy="300" r="50" />
  <svg>
</body>

Это добавляет узлы SVG непосредственно в DOM. Поэтому к SVG могут быть применены стили через CSS:

circle {
  stroke-width: 1em;
}

.mysvg {
  stroke-width: 5px;
  stroke: #f00;
  fill: #ff0;
}

Объем встроенного кода SVG уменьшается, а код CSS можно использовать повторно или анимировать по мере необходимости.

Избегайте растровых изображений Base64

Стандартные растровые изображения JPG, PNG и GIF могут быть закодированы с помощью base64. Например:

.myimg {
  background-image: url('data:image/png;base64,ABCDEFetc+etc+etc');
}

Но это неправильный подход:

  • кодировка base64 на 30% больше, чем ее двоичный эквивалент;
  • браузер должен проанализировать строку, прежде чем ее можно будет использовать;
  • изменение изображения делает недействительным весь кэшированный файл CSS.

Несмотря на то, что выполняется меньше HTTP-запросов, это редко дает заметное преимущество, особенно по сравнению с HTTP/2-соединениями.

Критический CSS

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

  1. Располагайте стили, используемые для визуализации элементов, выше первого сгиба. Такие инструменты, как criticalCSS, помогут вам в этом.
  2. Добавьте их в элемент <style> в раздел HTML <head>.
  3. Загружайте основной файл CSS асинхронно, используя JavaScript.

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

  • Невозможно определить линию сгиба для каждого устройства.
  • Большинство сайтов используют разные шаблоны страниц. Каждому из них может потребоваться различный критический CSS.
  • События, управляемые JavaScript, могут изменять элементы, расположенные выше первого сгиба.

Прогрессивный рендеринг

Прогрессивный рендеринг - это метод, который определяет отдельный CSS для отдельных элементов. Каждый загружается непосредственно перед ссылкой на компонент в HTML:

<head>

  <!-- основные стили, используемые для разных компонентов -->
  <link rel='stylesheet' href='base.css' />

</head>
<body>

  <!-- компоненты хедера -->
  <link rel='stylesheet' href='header.css' />
  <header>...</header>

  <!-- основной контент -->
  <link rel='stylesheet' href='content.css' />
  <main>

    <!-- стили форм -->
    <link rel='stylesheet' href='form.css' />
    <form>...</form>

  </main>

  <!-- компонент футера -->
  <link rel='stylesheet' href='footer.css' />
  <footer>...</footer>

</body>

Каждый элемент <link> по-прежнему блокирует рендеринг, но на более короткое время. Потому что файл меньше.

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

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

Научитесь любить CSS

Добавление огромного количества CSS из StackOverflow или Bootstrap может дать быстрые результаты. Но это также приведет к переполнению CSS неиспользуемым кодом.

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

Вадим Дворниковавтор-переводчик статьи «20 Tips for Optimizing CSS Performance»