Скорость страницы
Медленный сайт закрывают, не дождавшись: на телефоне с плохой связью каждая лишняя секунда заметна. Многое для скорости решается прямо в HTML и CSS — порядком загрузки, размерами картинок и тем, чтобы страница не прыгала во время загрузки.
Блокирующий CSS
Пока файл стилей из <head> не скачан, браузер ничего не рисует: иначе пользователь увидел бы голую разметку, которая потом перескочит. Поэтому CSS называют блокирующим отрисовку. Отсюда идея критического CSS: стили первого экрана — шапки и заголовка — кладут прямо в <style> в <head>, а остальное подключают обычным файлом. Первый экран появляется, не дожидаясь лишнего:
<head>
<style>/* только стили шапки и первого экрана */</style>
<link rel="stylesheet" href="style.css">
</head>Для небольшого сайта хватит простого правила: один файл стилей, без неиспользуемых библиотек.
preload и preconnect
Некоторые файлы браузер находит поздно — например, шрифт упомянут только внутри CSS. Тег <link rel="preload"> велит скачать файл сразу. preconnect заранее открывает соединение с чужим сервером, как в уроке «Веб-шрифты»:
<link rel="preload" href="fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">Предзагружайте только то, что точно нужно на первом экране: лишние preload отнимают канал у важных файлов.
Картинки
Картинки — самая тяжёлая часть большинства страниц. loading="lazy" откладывает загрузку, пока картинка не приблизится к видимой области, а fetchpriority="high" просит скачать главную картинку раньше остальных:
<style>
img { max-width: 100%; height: auto; display: block; margin-bottom: 8px; }
</style>
<img src="/media/photo-800x500.jpg" alt="Главное фото" width="800" height="500" fetchpriority="high">
<img src="/media/photo-400x250.jpg" alt="Фото ниже по странице" width="400" height="250" loading="lazy">Отдавайте файл нужного размера: картинка 4000 пикселей в окошке на 400 весит в десятки раз больше, чем надо. Для этого есть srcset из урока «Адаптивные изображения».
Без прыжков
Если размер картинки неизвестен, браузер сначала выделяет ей ноль пикселей, а когда файл придёт — раздвигает страницу. Текст прыгает вниз, и пользователь промахивается по кнопке. Это называют сдвигом вёрстки. Атрибуты width и height или свойство aspect-ratio резервируют место заранее:
<style>
.slot { aspect-ratio: 16 / 10; max-width: 320px; background: gainsboro; }
.slot img { width: 100%; height: 100%; object-fit: cover; }
</style>
<div class="slot"><img src="/media/photo-800x500.jpg" alt="Фото" loading="lazy"></div>
<p>Этот текст не сдвинется, когда фото загрузится.</p>Серый прямоугольник нужной формы стоит на месте ещё до загрузки.
content-visibility и contain
content-visibility: auto разрешает браузеру не отрисовывать блок, пока он далеко за пределами экрана. На длинных страницах это заметно ускоряет первый показ. contain-intrinsic-size подсказывает примерную высоту такого блока, чтобы полоса прокрутки не дёргалась:
<style>
section { content-visibility: auto; contain-intrinsic-size: auto 200px; padding: 8px; border-bottom: 1px solid silver; }
</style>
<section><h3>Глава 1</h3><p>Браузер рисует только видимые главы.</p></section>
<section><h3>Глава 2</h3><p>Остальные он пропускает до прокрутки.</p></section>Свойство contain — более ручной вариант: contain: layout paint обещает, что содержимое блока не влияет на остальную страницу, и браузер пересчитывает меньше.
Как измерить
Во вкладке Lighthouse инструментов разработчика (урок «Инструменты разработчика») есть отчёт Performance. Он ставит оценку и показывает главные показатели:
| Показатель | Что измеряет | Хорошо |
|---|---|---|
| LCP | когда отрисован самый крупный элемент первого экрана | до 2,5 с |
| CLS | сколько вёрстка прыгала при загрузке | до 0,1 |
| INP | как быстро страница отвечает на щелчки и нажатия | до 200 мс |
Проверяйте в режиме телефона: там медленнее процессор и связь.
Частая ошибка
loading="lazy" на главной картинке первого экрана. Браузер сначала строит страницу и только потом решает, видна ли картинка, — она начинает грузиться позже, и LCP ухудшается. Ленивая загрузка нужна картинкам ниже первого экрана, а главной ставят fetchpriority="high" без lazy.