В прошлой части мы вынесли десктопные стили в отдельный файл с атрибутом media, чтобы телефон их не ждал. У этого приёма есть две тонкости, о которые мы споткнулись уже после внедрения: одна возвращает блокировку отрисовки, вторая ломает вёрстку на определённой ширине.

Это тридцать первая часть цикла «PageSpeed без мифов».

1. Две строки сделали файл блокирующим

Атрибут media у отдельного файла — это самый низкий порог среди всех правил в нём. Если там только min-width: 768px и выше, телефон шириной 390 px файл не ждёт. Но достаточно одного правила с маленьким порогом — и весь файл становится блокирующим для телефонов.

У нас так случилось из-за двух правил на 48 байт: @media (min-width: 381px) и (min-width: 441px) — подгонка какой-то мелочи под чуть более широкие телефоны. Порог файла опустился до 381 px, и современные телефоны (390–430 px) снова ждали весь десктопный CSS. В отчёте — 450 мс из 850 на блокирующие стили.

Лечение: перевернуть такие правила на max-width — сделать «широкий» вариант базой, а узкий — исключением. Тогда они остаются в мобильном файле, и порог десктопного возвращается наверх.

# какие пороги есть в десктопном файле — самый маленький и станет media
grep -o 'min-width: *[0-9.]*px' main.mq.css | sort -u -k2 -n | head

2. Каскад: правило из десктопного файла побеждает

Файл с правилами min-width подключается после базового. Значит, при равной специфичности побеждает правило из него — даже если в исходном SCSS оно было написано раньше базового. До разделения порядок определял исходник, после — порядок файлов.

Что мы получали на практике, каждый раз ровно с ширины порога:

  • лишний отступ слева в 10 px у блока, который должен был от него избавиться;
  • object-fit: contain вместо cover у видео — и некрасиво скруглённые углы;
  • размер шрифта 70 px вместо 50;
  • скрытый слот, который снова становился видимым.

Признак этой проблемы: расхождение с макетом начинается ровно с какой-то ширины (у нас — с 561 px, порога разделения) и сохраняется на всех экранах шире, а ниже всё правильно. Если видите такое — смотрите в десктопный файл.

Лечение — специфичность, а не перестановка. Двигать правила в исходнике бесполезно: порядок теперь задают файлы. Нужно сделать «правильное» правило специфичнее — добавить класс-родитель или модификатор.

/* было: .card .media в базе проигрывает .card .media из @media в отдельном файле */
.card .media { object-fit: cover; }

/* стало: правило-исключение специфичнее */
.card.isVideo .media { object-fit: cover; }

Как не попадаться

  1. После включения разделения проверьте вёрстку на ширинах порогов и на 1–2 px выше каждого.
  2. Держите в мобильном файле всё, что меньше вашего главного порога: подгонки под «чуть шире» пишите через max-width.
  3. После каждой сборки смотрите, какой порог получил десктопный файл (команда выше).

Вёрстка «едет» с определённой ширины?

Пришлите адрес и ширину — найду правило, которое побеждает не то.

· полезно?
АЧ
Алексей Чикун веб-разработчик, команда TRIOHEAD

Делаю сайты и сервисы целиком: от вёрстки до сервера. Пишу о том, что проверил на своих проектах.

Комментарии

// загружаю комментарии…

Комментарии публикуются после проверки. Ссылки и HTML не принимаются.