Атрибут placeholder vs label

placeholder — это подсказка внутри поля ввода, которая исчезает при наборе текста; <label> — постоянная видимая метка поля, обязательная для доступности форм.

Зачем нужно

placeholder часто ошибочно используют вместо <label>, что делает формы недоступными: когда пользователь начинает вводить текст, подсказка исчезает, и он не помнит, что нужно ввести. Screen readers по-разному обрабатывают placeholder. <label> всегда виден, всегда программно связан с полем и является стандартом доступности (WCAG 1.3.1, 3.3.2).

Где используется

  • <label> — в любой форме: регистрация, оплата, поиск, настройки
  • placeholder — как вспомогательная подсказка о формате ввода (рядом с label)
  • Формы в SPA (React, Vue, Angular), нативные HTML-формы

label — правильно

Явная связь через for / id

<div class="field">
  <label for="email">Электронная почта</label>
  <input type="email" id="email" name="email" required>
</div>

Неявная связь (оборачивание)

<label>
  Пароль
  <input type="password" name="password" required>
</label>

placeholder как помощник к label

<div class="field">
  <label for="phone">Телефон</label>
  <input
    type="tel"
    id="phone"
    name="phone"
    placeholder="+7 (999) 123-45-67"
    autocomplete="tel">
</div>

Placeholder здесь показывает формат, но не заменяет label.

Сравнение placeholder и label

Критерий <label> placeholder
Виден при заполнении поля Да Нет — исчезает
Screen reader Всегда объявляет Непоследовательно (зависит от браузера)
Контрастность Контролируется CSS Обычно низкая (серый текст)
WCAG соответствие Требуется (1.3.1, 3.3.2) Не является заменой label
SEO / автозаполнение Помогает Не влияет

Частые антипаттерны

<!-- ПЛОХО: только placeholder, нет label -->
<input type="email" placeholder="Email" name="email">

<!-- ПЛОХО: label скрыт через display:none -->
<label for="name" style="display:none">Имя</label>
<input type="text" id="name" placeholder="Имя">

<!-- ХОРОШО: визуально скрытый label остаётся для screen readers -->
<label for="name" class="visually-hidden">Имя</label>
<input type="text" id="name" placeholder="Иван Иванов">
/* visually-hidden — стандартный паттерн */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

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

Ошибка Почему плохо Как правильно
placeholder вместо label Подсказка исчезает при вводе Всегда добавляй <label>
label без for / без обёртки Поле не связано с меткой Используй for="id" или оборачивай
Низкоконтрастный placeholder Нарушение WCAG 1.4.3 Контраст placeholder минимум 4.5:1
display:none на label Screen reader не видит метку Используй .visually-hidden

Связанные темы

Ресурсы