Альтернативный текст

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

Альтернативный текст — короткое описание, которое передаёт ту же информацию и ту же функцию, что и изображение, тому, кто это изображение не видит.

Зачем это на практике

Обычно alt вспоминают в связке «незрячий пользователь + скринридер», и это правда. Но список тех, кому alt спасает день, шире:

  • картинка не загрузилась — плохой интернет, упавший CDN, блокировщик;
  • человек экономит трафик и отключил изображения;
  • поисковый робот: alt — это то, по чему вас находят в поиске по картинкам;
  • человек с когнитивными трудностями, которому браузер читает страницу вслух;
  • умные часы и голосовые ассистенты, у которых экрана попросту нет.

Хороший alt — это не «галочка для аудита». Это резервный канал, который срабатывает в самый неудобный момент.

Главный вопрос: что эта картинка делает?

Прежде чем писать alt, определите тип изображения — от этого зависит всё остальное.

ТипПризнакЧто писать в alt
Информативноенесёт смысл, которого нет в тексте рядомсуть, а не описание пикселей
Декоративноеуберите его — ничего не потеряетсяalt="" (пусто)
Функциональноеэто ссылка или кнопкаописание действия, не картинки
Сложноеграфик, схема, инфографикакраткая суть + полное описание рядом

Практический приём: мысленно закройте картинку рукой. Смысл абзаца потерялся? Значит, информативная. Ничего не изменилось? Декоративная. Картинка — это кликабельная иконка? Функциональная, и alt должен отвечать на вопрос «что произойдёт, если я нажму», а не «что тут нарисовано».

Информативные изображения

Вот четыре реальных alt из продакшена. Все четыре плохие:

<img src="chart.png" alt="изображение">
<img src="chart.png" alt="график">
<img src="chart.png" alt="chart.png">
<img src="chart.png" alt="график, диаграмма, выручка, аналитика, 2025, отчёт">

Почему alt="изображение" бесполезен. Роль элемента скринридер объявляет сам — он и так скажет «изображение». В результате пользователь слышит «изображение, изображение»: секунда времени, ноль информации. Это хуже, чем пустой alt, потому что создаёт ложное впечатление, будто описание есть, и автоматический аудит проходит зелёным. То же с «фото», «картинка», «иконка», «баннер».

Четвёртый пример — набивка ключевыми словами. Поисковики её давно наказывают, а живой человек слышит шесть слов подряд и не понимает ни одного.

Хорошо:

<img src="chart.png"
     alt="Выручка выросла с 1,2 до 4,8 млн рублей за 2025 год">

Разница в подходе: плохой alt отвечает на вопрос «что здесь нарисовано», хороший — «что здесь важно».

Правила, которые экономят время

  • Не начинайте с «Изображение…», «Фото…» — роль уже объявлена. Исключение: когда тип носителя сам по себе информация: «Скриншот ошибки 500 в консоли браузера», «Портрет Ады Лавлейс, гравюра XIX века».
  • Ориентир по длине — примерно до 125 символов. Не влезаете? Значит, изображение сложное — см. раздел про графики.
  • Ставьте точку в конце. Скринридер сделает паузу, и alt не сольётся со следующим предложением.
  • Не дублируйте подпись под фото. Если рядом уже есть figcaption, alt должен говорить другое.
<figure>
  <img src="team.jpg" alt="Шесть человек стоят у доски, покрытой стикерами">
  <figcaption>Планирование спринта, март 2025</figcaption>
</figure>

Здесь alt рассказывает, что на фотографии, а подпись даёт контекст. Продублировать их — значит заставить человека слушать одно и то же дважды.

Декоративные изображения и волшебный alt=""

Разделитель, фоновый узор, абстрактная иллюстрация к абзацу, который и так всё сказал, — всё это шум. Пустой alt (именно пустой, без пробела внутри) — это команда «пропусти меня».

<img src="divider.svg" alt="">

Разница между «забыть alt» и «поставить alt=""» — принципиальная, хотя визуально в редакторе она незаметна:

РазметкаЧто услышит пользователь
<img src="hero-2025-final-2.png">«хиро дефис 2025 дефис файнал дефис 2 точка п н г, изображение»
<img src="hero.png" alt="">ничего — элемент пропущен
<img src="hero.png" alt="изображение">«изображение, изображение»
<img src="hero.png" alt="Кот спит на клавиатуре">«Кот спит на клавиатуре, изображение»

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

Совсем декоративное лучше вообще убрать из HTML — в CSS:

.hero {
  background-image: url("pattern.svg");
  background-size: cover;
}

Фоновые изображения скринридер не видит в принципе, и это ровно то, что нужно. Но осторожно: если картинка несёт смысл (логотип, схема, скриншот), прятать её в background-image нельзя — она исчезнет и для скринридера, и для поиска, и для режима высокой контрастности Windows.

Иконки-кнопки: alt описывает действие

Плохо — человек слышит «trash, кнопка»:

<button><img src="trash.svg" alt="trash"></button>

Хорошо — alt отвечает на вопрос «что будет, если нажать»:

<button type="button"><img src="trash.svg" alt="Удалить черновик"></button>

Если иконка — inline SVG, alt взять неоткуда, имя даёт aria-label:

<button type="button" aria-label="Удалить черновик">
  <svg aria-hidden="true" focusable="false" width="16" height="16">
    <use href="#icon-trash"></use>
  </svg>
</button>

Здесь два обязательных атрибута на самом SVG. aria-hidden="true" убирает графику из дерева доступности, чтобы она не добавляла шум поверх имени кнопки. focusable="false" лечит старый баг движка Trident/EdgeHTML, из-за которого SVG попадал в обход по Tab — на легаси-браузерах это до сих пор ловится.

А если рядом с иконкой есть текст, иконка автоматически становится декоративной, и никакого alt/aria-label ей не нужно — имя кнопки уже есть:

<button type="button">
  <svg aria-hidden="true" focusable="false" width="16" height="16"></svg>
  Удалить
</button>

Отдельный случай — логотип-ссылка. Пользователю важно, куда ведёт ссылка, а не что это логотип:

<a href="/"><img src="logo.svg" alt="CodeChick, на главную"></a>

Сложные изображения: графики, схемы, инфографика

В 125 символов не влезет столбчатая диаграмма за 12 месяцев — и не надо пытаться. Схема такая: alt = краткая суть, полное описание — рядом, в тексте.

Лучший вариант, как ни странно, самый простой: вывод из графика написать словами в соседнем абзаце. То, что важно незрячему, важно и зрячему — просто зрячий обычно ленится вглядываться в подписи осей.

Второй по надёжности приём — таблица с данными под графиком:

<figure>
  <img src="revenue-2025.png"
       alt="Диаграмма выручки по кварталам 2025 года; данные — в таблице ниже">
  <figcaption>Выручка по кварталам, 2025</figcaption>
</figure>

<table>
  <caption>Данные диаграммы: выручка по кварталам, млн рублей</caption>
  <tbody>
    <tr><td>I квартал</td><td>1,2</td></tr>
    <tr><td>II квартал</td><td>2,1</td></tr>
    <tr><td>III квартал</td><td>3,4</td></tr>
    <tr><td>IV квартал</td><td>4,8</td></tr>
  </tbody>
</table>

Таблица под графиком — лучший «длинный alt», который вообще придумали. Ей рады все: незрячий читает данные, зрячий копирует их в свою таблицу, поисковик индексирует.

Про атрибут longdesc, который предлагали для этого раньше, — просто забудьте: он объявлен устаревшим и браузерами не поддерживается.

И ещё два правила про «текст внутри картинки»:

  • Скриншоты кода — плохая идея. Такой код нельзя скопировать, увеличить, озвучить и найти поиском. Давайте текстовый блок <pre><code>.
  • Текст в изображениях (баннеры, цитаты картинкой) нарушает WCAG 1.4.5: он не масштабируется без размытия, не переводится и не перекрашивается в тёмной теме. Исключение — логотипы.

Как это работает

Когда браузер строит дерево доступности, для <img> он определяет роль узла прямо по значению alt:

  • alt="текст" → роль image, имя = текст;
  • alt="" → роль presentation, узел выкидывается из дерева;
  • alt отсутствует → роль image, имени нет; скринридер вынужден импровизировать и чаще всего читает src.

Имя, если alt не дал ответа, ищется дальше по цепочке: aria-labelledbyaria-labelalttitle → имя файла. Обратите внимание: aria-label на <img> перебьёт alt — этим иногда пользуются в компонентах, но правило «одно изображение — один источник имени» надёжнее.

Как проверить свои alt

  • Отключите картинки в браузере и перечитайте страницу. Всё ещё понятно? Значит, alt-ы работают.
  • Пройдите скринридером. NVDA бесплатен для Windows, VoiceOver уже встроен в macOS и iOS.
  • Помните про предел автоматики. axe и Lighthouse находят отсутствие alt. Осмысленность alt не проверит ни один линтер в мире: alt="изображение" для них — валидный alt. Это работа человека.

Частые ошибки

ОшибкаКак правильно
alt="изображение", alt="фото", alt="иконка"либо суть картинки, либо alt="", если она декоративна
Атрибут alt отсутствует у декоративной картинкиalt="" — иначе прочитают имя файла
alt="" у изображения-ссылки или кнопкикнопка останется без имени: alt = действие
alt дословно повторяет figcaptionalt — что на картинке, подпись — контекст
Набивка ключевыми словамиодно осмысленное предложение
SVG-иконка внутри кнопки без aria-hidden="true"иконка добавляет шум поверх имени кнопки
График с alt «диаграмма продаж»краткая суть + таблица с данными рядом
Смысловое изображение в background-imageсмысл — только в <img> с alt

Итоги

  • alt — замена изображения, а не подпись к нему. Пишите то, что важно, а не то, что нарисовано.
  • Атрибут alt нужен всегда: у декоративной картинки он пустой (alt=""), у информативной — осмысленный.
  • alt="изображение" хуже, чем пустой alt: он тратит время пользователя и обманывает автоматический аудит.
  • Картинка-кнопка и картинка-ссылка описываются действием: «Удалить черновик», «На главную».
  • Сложные графики: короткий alt плюс данные текстом или таблицей рядом. Это полезно всем, а не только незрячим.
  • Инструменты найдут отсутствующий alt, но никогда не оценят бессмысленный. Проверять смысл — вручную.
Проверьте себя
1. На странице лежит чисто декоративный SVG-разделитель между секциями. Как его разметить?
A<img src="divider.svg"> — без alt, и скринридер сам поймёт, что картинка неважная
B<img src="divider.svg" alt="разделитель"> — короткое честное описание
C<img src="divider.svg" alt=""> — пустой alt выкидывает элемент из дерева доступности
2. Кнопка удаления состоит из <button> и вложенной inline-SVG-иконки корзины. Какой вариант корректен?
A<button aria-label="Удалить черновик"><svg aria-hidden="true" focusable="false">…</svg></button>
B<button><svg role="img" aria-label="корзина">…</svg></button>
C<button title="trash"><svg>…</svg></button>