Мы поставили hero-картинке на главной атрибут loading="lazy" вместо привычного eager. Причина в том, что на мобильном эту же картинку скрывает display: none: у скрытого элемента нет области на экране, и браузер мог бы её вообще не трогать, а при eager он всё равно её качал. Разбираем, как на самом деле работает отложенная загрузка и почему учебниковый совет "первый экран грузите сразу" сработал у нас наоборот.
Правило звучит почти в каждом гайде по скорости одинаково: видимое грузим сразу, всё остальное - лениво. Мы следовали ему же, пока не сверили список сетевых запросов на телефоне с тем, что человек реально видит на узком экране. Сравнение показало: браузер честно тянул файл, которого в кадре не было ни секунды.
Как браузер решает, что грузить сразу, а что отложить
Атрибут loading="lazy" - штатная часть HTML, работает без единой строчки JavaScript. Браузер откладывает запрос картинки или iframe до момента, когда элемент подходит близко к видимой области, с небольшим запасом на прокрутку вперёд.
Разница ощутима на мобильном трафике: страница с длинной галереей не тянет разом полсотни файлов, а качает их по мере прокрутки.
С точки зрения кода это ничего не стоит. Цена появляется в другом месте: браузеру нужно сначала посчитать геометрию страницы, чтобы понять, близко элемент к экрану или нет, и только после этого принять решение о запросе.
Откуда взялось правило "первый экран грузим без задержки"
Совет привязан к метрике LCP - времени, за которое отрисовывается самый крупный видимый элемент. Подробно об этой и других метриках писали в статье Core Web Vitals 2026. Если LCP-элемент - картинка, и она отложена, браузер сначала заканчивает расчёт раскладки, потом решает, попадает ли картинка в зону загрузки, и только затем начинает её качать.
Эта ступень добавляет задержку именно тем элементам, которые и так должны появиться первыми. Правило верное ровно для одного случая: элемент реально виден при открытии страницы, без прокрутки.
Проблема в том, что "видим на макете" незаметно подменяет "виден у пользователя". У нас на десктопе hero-картинка занимает треть первого экрана, а на телефоне у той же секции другая раскладка, и картинку там решили не показывать вовсе.
Наш случай: элемент спрятан, а браузер всё равно тянет файл
display: none убирает элемент из потока документа полностью: у него нет ширины, высоты, координат, он не участвует в раскладке. Казалось логичным, что раз элемента нет на странице, то и качать его незачем.
Но с атрибутом eager это рассуждение не работает. Eager значит "начни загрузку сейчас, не дожидаясь условий". Браузер не проверяет ни видимость, ни display, ни то, попадёт ли элемент когда-нибудь в кадр - он просто выполняет команду. Картинка уходила в очередь на закачку вместе с остальными ресурсами первого экрана, хотя показать её было негде.
На мобильном трафике это чистые потери: файл занимал полосу пропускания и конкурировал за приоритет с нужными ресурсами. С loading="lazy" браузер видит, что элемент вне потока и никогда не окажется рядом с видимой областью, и запрос не отправляет.
Как проверить у себя: панель сети на узком экране
Разбор занимает пять минут. В браузере включаете эмуляцию мобильного экрана, открываете панель сети с фильтром по изображениям и перезагружаете страницу.
Дальше сравниваете два списка: что реально загрузилось и что видно на экране без прокрутки. Любой файл без соответствия на экране - кандидат на пересмотр атрибута загрузки. Проверяйте оба крайних случая, мобильный и десктопный: раскладка часто разная. Мы подробно писали про такие расхождения в статье про мобильную версию сайта.
Второй источник данных - отчёт вроде Lighthouse или PageSpeed Insights. Он прямо называет LCP-элемент для конкретного разрешения и показывает, стартовал тот сразу или с задержкой из-за очереди отложенной загрузки.
picture и srcset вместо display: none
display: none - не единственный способ показать разным экранам разный контент, и для картинок часто не лучший. Тег picture с несколькими source и условием media позволяет отдать мобильному разрешению другой файл или не отдавать картинку в принципе, ещё до того, как браузер решит её качать.
Отличие принципиальное: display: none прячет уже запрошенный элемент средствами CSS, а picture с media решает вопрос на уровне выбора ресурса, до сетевого запроса. Браузер читает условия media, находит подходящий source и запрашивает только его.
Мы разбирали адаптивную раскладку отдельно в статье про 6 брейкпойнтов и типичные провалы: там же логика, что решение "показывать или нет" правильнее принимать до загрузки ресурса, а не после неё.
Почему прятать готовое стилями - плохая привычка
display: none для целых секций - удобный инструмент, мы сами используем его для мобильного меню. Проблема не в свойстве, а в привычке применять его к тяжёлым ресурсам без учёта того, что стили и загрузка ресурсов - разные этапы обработки страницы.
CSS решает, что показать. Сеть решает, что скачать. Эти два решения не всегда успевают связаться друг с другом, особенно когда атрибут загрузки прямо говорит "качай сейчас". Правило простое: если ресурс тяжёлый - картинка, видео, встроенная карта - решение о его показе стоит принимать до того, как ресурс запрошен, а не после.
Для текста это не имеет значения: скрытая строка не тянет отдельный запрос. Для картинок, видео и карт счёт идёт на сотни килобайт, и там разница между "решили не показывать" и "решили не качать" превращается в секунды загрузки на слабом канале.
Карты и видео: где отложенная загрузка экономит больше всего
Встроенная карта Яндекса или Google в iframe и видеоплеер - самые тяжёлые постоянные элементы на большинстве сайтов, тяжелее почти любой картинки. Карта тянет за собой скрипты, тайлы и шрифты, видеоплеер - обвязку интерфейса и превью кадров ещё до нажатия play.
На loading="lazy" оба элемента реагируют так же, как картинка: iframe не начинает загрузку, пока не окажется рядом с видимой областью. Для карты на странице контактов, которая обычно ниже первого экрана, это экономит львиную долю веса страницы при первом заходе. Про подключение видео и типичные ошибки с его весом писали отдельно в материале видео на сайте.
Отдельный случай - видео и карта в первом экране на десктопе, но скрытые на мобильном тем же приёмом display: none, что и наша hero-картинка. Логика та же: eager у скрытого iframe так же бессмысленно грузит содержимое, которое никто не увидит, только цена ошибки выше в разы из-за веса.
Чек-лист: куда какой атрибут ставить
Порядок действий, который мы теперь проходим на каждом новом проекте перед сдачей.
- Открыть страницу на узком экране, посмотреть панель сети, выписать всё, что грузится до первого клика.
- Сверить список с тем, что реально видно без прокрутки на этом разрешении.
- Всему, что видно сразу и на всех разрешениях, - eager, без исключений.
- Всему, что видно только ниже первого экрана, - lazy.
- Всему, что скрыто на части разрешений через display: none или media-запросы, - lazy как минимум, а по возможности переезд на picture с условием media.
- Для самого крупного видимого элемента первого экрана - дополнительно fetchpriority="high".
- Проверить отчёт по скорости после правок: LCP-элемент должен стартовать без задержки, лишние запросы - пропасть из списка сети.
Если заказываете разработку на стороне, стоит спросить у подрядчика, проверял ли он список сетевых запросов на мобильном экране отдельно от десктопного - это быстрый способ понять, работали ли с сайтом на уровне вёрстки или только на уровне визуального макета. Про такие технические вопросы к разработке подробно писали в материале про ускорение сайта.
Что решает не атрибут, а вёрстка
Атрибут loading - не переключатель "быстро или медленно", а условие запроса: eager качает сразу и безусловно, lazy - только рядом с видимой областью. У нас вёрстка прятала элемент одним способом, а загрузка была настроена другим, и эти два решения жили каждое само по себе. Простое правило на будущее: прячете тяжёлый ресурс стилями хотя бы на части разрешений - проверяйте отдельно, что происходит с его загрузкой. Иногда достаточно lazy, иногда правильнее вообще не грузить этот вариант через picture и media. Учебниковое правило "первый экран - eager" остаётся верным ориентиром, но проверять его стоит по факту в панели сети, а не по тому, что нарисовано в макете.
Если хотите, чтобы такие мелочи проверяли на этапе разработки, а не находили это через полгода после запуска, посмотрите, как мы собираем сайты в разделе корпоративные сайты: там же порядок работы и что входит в техническую приёмку.

