Картинки: место заранее, alt и щель под строчной картинкой

разметка≈ 12 минут

Здесь будет встроен видео-разбор темы (5–7 минут, YouTube / RuTube / VK Видео) — тем, кто лучше воспринимает на слух, текст ниже не обязателен.

Страница открылась, вы начали читать — и абзац уехал вниз, потому что над ним догрузилась картинка. Знакомая ситуация: палец уже нажал ссылку, а под ним оказался другой текст. Браузер здесь не виноват. Размер картинки записан в её файле, а файл приходит позже разметки, и до его прихода браузер не знает, сколько места оставить. Разберём, что происходит с коробкой картинки, файла которой ещё нет, как двумя атрибутами отложить под неё место, что писать в alt — и откуда под картинкой берётся щель, которую никто не задавал.

Разделы темы:·

Разметка приходит первой, картинки — следом, каждая отдельным запросом, и на медленной сети между ними проходят секунды. Браузер не ждёт: он показывает текст сразу, а картинки вставляет по мере прихода. Сколько места оставить под картинку, файл которой ещё в пути? Размер записан в самом файле, и если разметка о нём молчит — нисколько. Файл пришёл, коробка выросла, и всё, что ниже, съехало. Человек в этот момент дочитывал абзац или тянулся пальцем к кнопке, а попал в соседнюю.

Проверим на примере. В песочнице файлу неоткуда прийти, поэтому у картинок вовсе нет адреса src — и для коробки это ровно то же состояние, что и файл в пути: браузер строит её, ничего не зная о размере. Ниже две карточки шириной 200 пикселей, в каждой картинка и подпись. У первой картинки есть атрибуты width="400" и height="300" — размер её файла в пикселях, у второй их нет. Зачем обеим пустой alt="", станет ясно в разделе про alt.

<style> здесь уже не только для вида, поэтому прочитаем его. Правило стиля начинается с адреса элементов — такого же, как в вызовах прибора, — а за ним в фигурных скобках идут пары «свойство: значение». .box { width: 200px; } даёт элементам с классом box ширину 200 пикселей: точка в адресе означает класс. Правило для img растягивает картинку на всю ширину карточки (width: 100%), высоту оставляет вычислить браузеру (height: auto) и ставит картинку отдельной полосой (display: block — зачем, покажет раздел о щели). Язык стилей целиком разбирает вторая глава пролога.

Замер отвечает числом по каждому найденному элементу, в порядке разметки: height — высота, y — расстояние от верхнего края области, куда легла разметка. Прогноз: какой высоты окажутся две картинки и как высоко встанут обе подписи? Все числа назовёт разбор под примером — строка вывода в этой статье спрятана, ответ читается там.

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера
разбор вывода
Первая картинка — 150 пикселей. Ширину ей задал стиль, а высоту браузер вывел из атрибутов: 400 на 300 — это пропорция 4 : 3, и при ширине 200 высота выходит 150. Вторая — ноль: ни файла, ни атрибутов, выводить не из чего. Подписи начинаются на 164 и на 213. Первая — 150 пикселей картинки и 14 пикселей отступа, который браузер сам ставит над абзацем. Вторая — 164, строка первой подписи (21 пиксель), отступ под ней (14) и отступ над второй подписью (14), а от второй картинки — ничего; 14 и 21 получаются из размера текста в рамке примера, 14 пикселей. Когда придёт файл второй картинки — пусть тоже 400 на 300, — её коробка вырастет до 150, и вторая подпись уедет с 213 на 363. Это и есть прыжок. Атрибуты при этом превратились в aspect-ratio: у первой картинки он стал auto 400 / 300, у второй остался auto, то есть «узнаю из файла».

Сдвиг вёрстки измеряют: в Lighthouse и в отчётах Google о скорости сайта он называется CLS, и картинки без размеров — одна из частых его причин.

Отсюда привычка, которая закрывает тему сдвигов: у каждой картинки в разметке стоят width и height — настоящие размеры файла, — а то, какого она будет размера на экране, решает стиль. Две строки в таблице стилей, max-width: 100% и height: auto, есть почти в любом современном сбросе именно поэтому. Записанные в атрибуты числа при этом не мешают: они дают пропорцию, а масштаб берёт на себя стиль.

Атрибуты width и height браузер превращает в свойство стиля — aspect-ratio, «соотношение сторон». В <style> примера такого свойства нет, и всё же третья строка разбора его показывает: у картинки с атрибутами там пропорция парой чисел, у картинки без них — просто auto, то есть «узнаю из файла».

Слово auto перед парой чисел — оговорка: «пока файла нет, держи 400 к 300, а когда он придёт, возьми пропорции самого файла». Поэтому в атрибуты пишут настоящий размер файла. Ошибётесь — прыжок всё равно случится, только позже: место отложено под 4 : 3, а пришёл, скажем, квадрат, и коробка вытянется до 200 на 200.

Без всякого стиля атрибуты задают и сам размер: <img width="200" height="150"> займёт 200 на 150 пикселей. Но колонка на телефоне бывает уже картинки, поэтому ширину обычно отдают стилю — и тут легко попасть в ловушку. Ниже у обеих картинок width: 100%, а height: auto есть только у второй: его даёт класс fit. Прогноз для двух строк разбора: какой ширины и какой высоты окажется каждая картинка?

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера
разбор вывода
Ширина у обеих 200, а высота первой осталась 300 — из атрибута: width: 100% перебило ширину, высоту никто не трогал. Файл 400 на 300, когда придёт, сожмётся по ширине вдвое, в коробку 200 на 300. У второй картинки height: auto отменил высоту из атрибута, и в дело вступила пропорция — 150.

Атрибуты width и height работают как самый слабый стиль: любое правило CSS их перебивает, но только в том свойстве, которое в правиле названо. А height: auto отменяет высоту из атрибута — и в дело вступает пропорция.

Поэтому в стилях почти любого сайта для картинок стоят две строки: ширина не больше колонки и height: auto. Вместо width: 100% там часто пишут max-width: 100% — «не шире родителя»: большая картинка сжимается до колонки, а маленькая остаётся своего размера и не расплывается. Разницу проверите в третьей задаче.

Соотношение сторон можно задать и самому, без атрибутов, — например, рамке под видео: aspect-ratio: 16 / 9. У свойства статус Baseline Widely available с 20 марта 2024 года — пишите. А узнать из скрипта, что файл картинки наконец пришёл, можно по событию load: его разбирает часть II в статье про порядок загрузки страницы.

Картинку видят не все. Программа чтения с экрана произносит вместо неё текст из alt. Тот же текст браузер показывает на месте картинки, файл которой получить не удалось, а поисковик по нему понимает, что на картинке. Поэтому alt — не подпись и не имя файла, а замена: какой текст поставить на это место, чтобы человек, который картинку не видит, ничего не потерял.

КартинкаaltПочему так
фото товараalt="Пять красных роз в крафтовой бумаге"того, что видно на фото, в тексте рядом нет
логотип внутри ссылки на главнуюalt="Ромашка — на главную"другого текста у ссылки нет, и alt становится её именем
волнистая линия между разделамиalt=""ничего не сообщает: пустой alt просит программу чтения её пропустить
график, числа которого стоят в таблице нижеalt="Продажи за год, числа — в таблице ниже"пересказывать таблицу незачем, достаточно сказать, где данные

Пустой alt="" и отсутствие alt — разные сообщения. Пустой значит «украшение, пропусти». Без атрибута программа чтения не знает, важна ли картинка, и нередко читает вместо неё имя файла — что-нибудь вроде «IMG_2044.jpg»: человек услышит его вслух и не поймёт ничего. Разницу видно и в разметке. Квадратные скобки в адресе проверяют атрибут: img[alt] — картинки, у которых alt есть, img[alt=''] — у которых он есть и пуст; кавычки вокруг пустого значения одинарные, чтобы не спутаться с двойными вокруг всего адреса. Прогноз: сколько картинок найдёт каждый из трёх адресов?

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера
разбор вывода
img[alt] нашёл две картинки: пустой alt — тоже alt. Без атрибута осталась только третья.

Картинки без alt первыми ищут проверки доступности. Такой поиск вы соберёте сами в конце второй главы, в проекте с проверкой разметки на селекторах.

Чаще всего сомнение вызывает не фотография, а мелочь: иконка в кнопке, разделитель-завитушка, флажок страны. Правило одно — спрашивайте, что потеряет человек, который этого не увидит. Иконка корзины рядом со словом «Корзина» не добавляет ничего, значит alt="". Картинка-разделитель не несёт смысла — тоже alt="". А вот скриншот с текстом или график, из которого читается вывод, требует настоящего пересказа: «график: посещаемость выросла вдвое после переноса на статику», а не «график.png».

Теперь посмотрите в рамку. Файлы logo.png и остальные браузер даже не запрашивал: у документа песочницы адрес about:srcdoc, и полный адрес файла от него не достроить. Как относительный путь достраивается от адреса обычной страницы, объясняет статья про относительные адреса. Файла не будет — и на месте первой картинки браузер написал её alt. Две другие в Chrome и Firefox следа в рамке не оставили, но для программы чтения третья так и осталась картинкой без имени.

Отсюда и alt="" в первом примере статьи. Картинка без адреса для браузера — картинка, файла которой не будет, и текст из alt он выводит на её место. С текстом в alt замер получил бы высоту строки вместо нуля. Пустой alt оставляет голую коробку — такую же, как у картинки, файл которой ещё в пути: пока файл идёт, текст alt не показывается. Проверьте: впишите второй картинке первого примера alt="Букет" и запустите его снова.

alt не начинают словами «картинка» или «фото»: программа чтения сама сообщит, что перед ней изображение.

Последняя странность — щель в несколько пикселей под картинкой, которая стоит в блоке одна. Ни отступов, ни рамок, а блок выше картинки. Дело в том, что <img> по умолчанию строчный элемент: display у него inline, и он встаёт в строку текста, как слово, а не занимает свою полосу, как абзац. Всё в строке выравнивается по базовой линии — той, на которой стоят буквы, а под ней оставлено место для хвостов у «у», «р» и «д». Картинка садится нижним краем на базовую линию, и место для хвостов остаётся под ней пустым, даже если букв в строке нет.

В примере два блока, в каждом картинка 100 на 50 пикселей. Длинный src, который начинается с data:, — это сам файл, записанный прямо в адресе: крошечная картинка, которой не нужна сеть, иначе пример зависел бы от загрузки. Пробел в адресе значит «внутри»: .fixed img — картинки внутри элемента с классом fixed, и стиль даёт им display: block; запись .plain, .plain img через запятую означает сам блок и картинку в нём. Высота щели зависит от шрифта, поэтому в пикселях числа у разных читателей разошлись бы, и здесь работает сравнение: same отвечает «одинаково» или «по-разному» для всех найденных элементов. Прогноз для каждого блока: одинаковы ли высоты блока и его картинки?

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера
разбор вывода
В первом блоке высоты разные: блок выше картинки как раз на щель. Во втором одинаковые: блочной картинке строка не нужна, и места для хвостов букв под ней нет.

display: block подходит картинке, которая стоит отдельно: в карточке, над подписью. Если картинка должна остаться в строке, щель убирает vertical-align — свойство, которое говорит строчному элементу, по чему выравниваться. Со значением top или bottom картинка встаёт по верхнему или нижнему краю строки, а не на базовую линию, и пустое место под ней пропадает.

С этой щелью связан «почти стандартный» режим из статьи о скелете страницы: от старых правил в нём осталась как раз высота строки, в которой одна картинка и нет текста, и щели там нет. В стандартном режиме, который включает <!doctype html>, щель есть, и убирать её — дело вашего стиля.

Щель редко мешает в одиночку, зато в карточках её видно сразу: сетка из трёх карточек, в каждой картинка и подпись, и у всех карточек подпись отстоит от картинки на три-четыре лишних пикселя. Пустяк, из-за которого карточки выглядят неровно, а высоты в сетке перестают совпадать. Второй частый случай — иконка в строке текста: она стоит на базовой линии и растягивает строку. Лечат оба одним из двух способов: display: block, если картинка стоит отдельно, или vertical-align, если она обязана остаться в строке.

Ещё два атрибута картинки держатся на сети, поэтому в песочнице их не проверить — о них достаточно знать.

loading="lazy" откладывает загрузку, пока до картинки далеко: файл начнёт скачиваться, когда читатель долистает близко. На длинной странице с галереей это экономит трафик и время. У ленивой загрузки картинок и фреймов статус Baseline Widely available с 19 июня 2026 года — пишите. Условий два. Картинкам первого экрана lazy не ставят: они нужны сразу, а ленивая загрузка их задержит. И ленивой картинке width и height нужнее, чем любой другой: пока до неё не долистали, файла нет наверняка.

srcset перечисляет файлы одной картинки разного размера, например srcset="rose-400.jpg 400w, rose-800.jpg 800w", и браузер сам выбирает, какой скачать: телефону с узким экраном незачем тянуть фото шириной 2400 пикселей. Рядом пишут sizes — подсказку, какой ширины картинка будет на странице: файл выбирается раньше, чем страница разложена. src при этом остаётся файлом по умолчанию. У srcset и sizes статус Baseline Widely available с 27 сентября 2019 года.

Проверяют и то и другое на настоящей странице: во вкладке Network инструментов разработчика видно, какие файлы скачались и в какой момент.

  • Файл картинки приходит позже разметки. Без width и height коробка до его прихода нулевая, и всё, что ниже, прыгает, когда файл придёт.
  • Атрибуты width и height браузер превращает в aspect-ratio: из 400 и 300 получается auto 400 / 300. С width: 100% или max-width: 100% и height: auto место откладывается в нужной пропорции при любой ширине колонки. В атрибуты пишут настоящий размер файла: когда он придёт, верх возьмут его пропорции.
  • Атрибуты — самый слабый стиль: CSS перебивает их по одному свойству. Забытый height: auto оставляет высоту из атрибута, и картинка сожмётся только по ширине.
  • alt — замена картинки текстом: осмысленный у содержательной картинки, пустой alt="" у украшения. Без атрибута программа чтения может прочитать имя файла.
  • <img> — строчный элемент и стоит на базовой линии, а щель под ним — место для хвостов букв. Её убирает display: block или, у картинки в строке, vertical-align: top или bottom.
  • loading="lazy" (Baseline Widely available с 19 июня 2026 года) не ставят картинкам первого экрана и не пишут без размеров. srcset даёт браузеру выбрать файл под экран. В песочнице ни то ни другое не проверить: сети там нет.

1/4Колонка шириной 300 пикселей, у картинки width="600" height="400", в стиле img { width: 100%; height: auto; }. Какой высоты её коробка, пока файл не пришёл?

2/4В стиле сайта img { width: 100%; }, у картинки width="400" height="300", колонка 200 пикселей. Что увидит читатель, когда файл придёт?

3/4Между разделами статьи стоит декоративная волнистая линия — картинка. Какой alt ей нужен?

4/4Картинка стоит в блоке одна, отступов и рамок нет, а блок на несколько пикселей выше неё. Почему?

Карточка, которая прыгает

Карточка букета шириной 200 пикселей: фото и подпись. Файл фото — 800 на 600 пикселей, адреса в примере нет: в песочнице файл всё равно не придёт. Сейчас место под фото не отложено, и подпись стоит там, куда фото потом упадёт.

Исправьте разметку и стиль: место под фото должно резервироваться заранее, щели под фото быть не должно, а программа чтения должна знать, что на нём. Когда всё получится, прибор напечатает img → height: 150px и .cap → y: 164px.

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера

Правок три. Атрибуты width="800" height="600" дают пропорцию 4 : 3, а height: auto в стиле её включает: при ширине 200 высота 150. display: block убирает строку, в которой стояла картинка, а с ней и щель. alt описывает фото.

jsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

Вывод: img → height: 150px и .cap → y: 164px. В исходном варианте подпись стояла на 35, хотя высота картинки была 0: пустая строчная картинка всё равно занимала строку текста в 21 пиксель, и к ней добавлялся отступ абзаца 14. Если вписать alt, но забыть display: block, высота будет не 150, а высотой текста: картинка без адреса, стоящая в строке, выводит свой alt как слова.

alt для витрины

На витрине магазина три картинки: логотип внутри ссылки на главную, волнистая линия-украшение и фото букета, о котором рядом написаны только название и цена. alt расставлен как попало. Исправьте так, чтобы каждая картинка сообщала программе чтения то, что нужно, и ни одна не осталась без атрибута.

Проверка считает только атрибуты, смысл решаете вы. В исправленной версии вывод такой: img[alt] → 3 и img[alt=''] → 1.

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера

Логотип — единственное содержимое ссылки, и его alt становится её именем: без него программа чтения скажет только «ссылка» и может прочитать адрес или имя файла. Линия ничего не сообщает — ей пустой alt, а не описание. У фото в alt стояло имя файла, а нужен текст о том, что на фото видно.

jsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

Вывод: img[alt] → 3 и img[alt=''] → 1.

Маленькая картинка расплылась

В колонке шириной 200 пикселей две картинки: фото 400 на 300 и значок 120 на 90. Стиль растягивает обе на всю ширину, и значок, растянутый почти вдвое, расплывётся. Замените в стиле одно свойство так, чтобы большая картинка сжималась до колонки, а маленькая оставалась своего размера. Нужный вывод: img → width: 200px, 120px и img → height: 150px, 90px.

js
разметка страницы
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
Tab добавляет отступ. Чтобы выйти из редактора, нажмите Escape — фокус перейдёт на кнопку запуска.
страница примера

width: 100% меняется на max-width: 100%. Ширину тогда задают атрибуты, а стиль только не пускает её дальше колонки: 400 урезается до 200, 120 остаётся 120. Высоту по-прежнему считает пропорция — за это отвечает height: auto.

jsлистинг · не запускается
Листинг только для чтения: этот код не запускается в браузере.

Вывод: img → width: 200px, 120px и img → height: 150px, 90px.