Тег <input> — самый многоликий в HTML. Один и тот же пустой элемент без закрывающего тега умеет быть строкой для имени, календарём, ползунком громкости, палитрой, кнопкой загрузки файла и даже невидимым полем. Всё решает один атрибут — type. Значений у него больше двадцати, и новички обычно ограничиваются text, а остальное дописывают на JavaScript.

Ниже — все типы, сгруппированные по задаче, которую они решают, с подвохами каждого. А в конце — шпаргалка по атрибутам: какой из них с каким типом вообще работает.

Что на самом деле меняет type

Смена type — это не косметика. Браузер получает подсказку сразу в четырёх местах:

  • клавиатура на телефоне — для email появится кнопка @, для tel — цифровая панель;
  • встроенная проверка — форма не отправится, пока значение не подходит под тип;
  • виджет — календарь, палитра, ползунок, окно выбора файла;
  • формат значения — например, дата всегда приходит в виде 2026-03-14, как бы она ни выглядела на экране.

Если браузер не знает указанный тип, он молча превращает поле в обычное текстовое. Поэтому новые типы безопасно ставить сразу: в худшем случае пользователь получит привычную строку ввода.

<label for="nickname">Никнейм</label>
<input type="text" id="nickname" name="nickname">

<!-- опечатка в типе — браузер покажет обычное text-поле -->
<input type="emial" name="contact">

Атрибут for у подписи должен совпадать с id поля, иначе клик по тексту не поставит фокус в поле, а скринридер не прочитает подпись. Ошибка банальная, но встречается даже в учебных примерах. Почему подпись нельзя заменить подсказкой внутри поля — в статье placeholder — это не label.

Текстовые поля, которые умнее text

Все эти типы выглядят как одна строка ввода, но ведут себя по-разному.

<input type="email" name="email" multiple>
<input type="url" name="site" placeholder="https://example.com">
<input type="tel" name="phone" pattern="\+?[0-9 \(\)\-]{7,20}">
<input type="search" name="q">
<input type="password" name="password" minlength="8">
  • email проверяет, что в строке есть @ и что-то до и после неё. С атрибутом multiple принимает несколько адресов через запятую.
  • url требует абсолютный адрес со схемой: example.com не пройдёт, https://example.com пройдёт. Если нужен строго https, добавьте pattern="https://.*". Как проверять адреса уже в коде — в статье про валидацию URL в JavaScript.
  • tel ничего не проверяет: форматы номеров в разных странах слишком разные. Он только открывает цифровую клавиатуру, а правило задаёт pattern.
  • search — то же текстовое поле, но браузер знает, что это поиск: в Chromium и Safari появляется крестик очистки, а на мобильных клавиша ввода превращается в «Найти».
  • password прячет символы за точками. Менеджеры паролей опознают поле именно по этому типу, а с правильным autocomplete браузер ещё и предложит сгенерировать надёжный пароль — подробно в статье про формы логина и регистрации.

number: значение всё равно строка

type="number" пропускает только число, рисует стрелки-счётчики и понимает min, max и step. Но свойство value в JavaScript всё равно возвращает строку. Число берут из valueAsNumber; у пустого поля там будет NaN.

<input type="number" id="qty" name="qty" min="1" max="99" step="1" value="2">
const qty = document.querySelector('#qty');

qty.value + 1;         // '21' — склейка строк
qty.valueAsNumber + 1; // 3

Номер карты, PIN-код, код из СМС, почтовый индекс и номер телефона через number не делают. Это не числа, а наборы цифр: при переводе в число пропадёт ведущий ноль, стрелки на клавиатуре прибавят к PIN единицу, а в поле можно вписать букву e — для браузера это часть экспоненциальной записи числа. Для таких полей берут type="text" с inputmode="numeric" — цифровая клавиатура будет, а лишнего поведения нет. Про inputmode подробнее — в подборке недооценённых HTML-атрибутов.

<input type="text" name="otp" inputmode="numeric" pattern="[0-9]{6}" autocomplete="one-time-code">

Дата и время

Пять типов открывают системный выбор даты или времени. Пользователь видит формат своей локали (например, 14.03.2026), а в value и на сервер всегда уходит машиночитаемая строка:

Тип Что выбирают Формат value
date день, месяц, год 2026-03-14
time часы и минуты 09:30
datetime-local дату и время, без часового пояса 2026-03-14T09:30
month месяц и год 2026-03
week неделю и год 2026-W11

Границы задают min и max в том же формате, что и значение. step у date считается в днях, у time — в секундах: step="900" оставит только слоты по 15 минут, а шаг меньше 60 добавит в поле секунды.

<label for="checkin">Заезд</label>
<input type="date" id="checkin" name="checkin" min="2026-03-01" max="2026-12-31">

<label for="slot">Время звонка</label>
<input type="time" id="slot" name="slot" min="09:00" max="18:00" step="900">

Слова «без часового пояса» у datetime-local важны: 09:30 из Киева и 09:30 из Варшавы придут на сервер одинаковыми. Если момент времени должен быть абсолютным, пояс пользователя передают отдельно.

date и time сегодня работают везде:

Поддержка браузерами
chrome
Chrome
20
firefox
Firefox
57
edge
Edge
12
safari
Safari
14.1
opera
Opera
11

С datetime-local история длиннее. Сам тип давно поддерживается, но Firefox до версии 154 показывал для него только календарь, а время приходилось вбивать руками. Выбор времени там появился вместе с починкой type="time" (bug 1726107). Safari по-прежнему показывает календарь без выбора времени, и это сознательное решение команды WebKit.

Поддержка браузерами
chrome
Chrome
20
firefox
Firefox
154
edge
Edge
12
safari
Safari
14.1
opera
Opera
11

С month и week хуже всего: в Firefox и десктопном Safari они остаются простыми текстовыми полями, без календаря и без проверки формата. Если без выбора недели не обойтись, нужен запасной вариант — два <select> или JS-календарь.

Поддержка браузерами
chrome
Chrome
20
firefox
Firefox
 
edge
Edge
12
safari
Safari
 
opera
Opera
11

Выбор из вариантов

checkbox и radio

Флажок — независимое «да/нет»: можно отметить сколько угодно. Переключатели объединяются в группу одинаковым name, и отмеченным в группе может быть только один. Атрибут checked отмечает вариант при загрузке и работает только у этих двух типов.

<fieldset>
  <legend>Доставка</legend>
  <label><input type="radio" name="delivery" value="courier" checked> Курьер</label>
  <label><input type="radio" name="delivery" value="pickup"> Самовывоз</label>
</fieldset>

<label><input type="checkbox" name="gift" value="yes"> Упаковать как подарок</label>

Неотмеченный флажок в данные формы не попадает вовсе — сервер не получит ни gift=no, ни пустую строку. А отмеченный без атрибута value отправит gift=on. Группу переключателей удобно оборачивать в <fieldset>: <legend> станет общей подписью для скринридера. Как оформить такую рамку — в статье про fieldset и legend.

У флажка есть свежий атрибут switch: он рисует системный переключатель вместо квадратика. Пока это предложение в WHATWG, а не часть спецификации, и поддерживает его только Safari. Остальные браузеры атрибут игнорируют и показывают обычный флажок, так что ничего не сломается.

<label><input type="checkbox" name="dark" switch> Тёмная тема</label>
Поддержка браузерами
chrome
Chrome
 
firefox
Firefox
 
edge
Edge
 
safari
Safari
17.4
opera
Opera
 

range: ползунок

Подходит, когда точное значение не так важно, как примерное: громкость, яркость, «насколько вам понравилось». По умолчанию диапазон от 0 до 100 с шагом 1, а начальное значение стоит посередине. Сам ползунок число не показывает, поэтому его выводят рядом через <output>.

<label for="volume">Громкость</label>
<input type="range" id="volume" name="volume" min="0" max="10" step="1" value="4">
<output for="volume" id="volume-value">4</output>
const volume = document.querySelector('#volume');
const volumeValue = document.querySelector('#volume-value');

volume.addEventListener('input', () => {
  volumeValue.value = volume.value;
});

color: палитра

Открывает системный выбор цвета. Значение всегда приходит семисимвольным hex в нижнем регистре, вроде #3a7bd5, а у пустого поля по умолчанию стоит #000000. Названия цветов и короткая запись вида #fff в value не принимаются.

<label for="accent">Цвет акцента</label>
<input type="color" id="accent" name="accent" value="#3a7bd5">
Поддержка браузерами
chrome
Chrome
20
firefox
Firefox
29
edge
Edge
14
safari
Safari
12.1
opera
Opera
11

В спецификацию недавно добавили атрибуты alpha (выбор прозрачности) и colorspace="display-p3" (широкий цветовой охват). Пока их поддерживает только Safari начиная с 18.4, поэтому в рабочих формах на них рассчитывать рано.

file: загрузка файлов

Рисует кнопку, которая открывает системный диалог выбора файла. accept сужает выбор по MIME-типу или расширению, multiple разрешает выбрать несколько файлов сразу. Чтобы файл ушёл на сервер, у формы должно быть method="post" и enctype="multipart/form-data".

<form action="/upload" method="post" enctype="multipart/form-data">
  <label for="photos">Фото товара</label>
  <input type="file" id="photos" name="photos" accept="image/png, image/jpeg, .webp" multiple>
  <button>Загрузить</button>
</form>

accept — только фильтр в диалоге, а не проверка: пользователь может переключить его на «Все файлы». Тип и размер файла всё равно проверяют на сервере. В JavaScript выбранные файлы лежат в свойстве files, а value из соображений приватности возвращает поддельный путь C:\fakepath\имя-файла. Как показать превью картинки до отправки — в статье про предпросмотр перед загрузкой, а атрибут capture для камеры телефона разобран в подборке атрибутов.

Подсказки через datalist

Ни в одном типе нет готового автодополнения, но его даёт атрибут list. Он связывает поле с <datalist>, и браузер показывает варианты по мере ввода. В отличие от <select>, вписать своё значение тоже можно.

<label for="city">Город</label>
<input type="text" id="city" name="city" list="cities">
<datalist id="cities">
  <option value="Kyiv">
  <option value="Lviv">
  <option value="Warsaw">
  <option value="Berlin">
</datalist>

Firefox поддерживает <datalist> частично: у полей даты и времени подсказок там не будет.

Поддержка браузерами
chrome
Chrome
69
firefox
Firefox
4
edge
Edge
79
safari
Safari
12.1
opera
Opera
56

Кнопки и служебные поля

Четыре типа превращают <input> в кнопку:

  • submit — отправляет форму, текст кнопки берётся из value;
  • reset — возвращает все поля к исходным значениям. В реальных формах его ставят редко: случайный клик стирает всё введённое;
  • button — кнопка без собственного поведения, только для JavaScript;
  • image — картинка, работающая как submit. Нужны src и alt, а размер задают width и height. Вместе с формой она отправляет координаты клика: name.x и name.y.

В новом коде вместо этих типов обычно пишут элемент <button>: внутри него можно разместить иконку и любую разметку, а не только текст из value. Ведёт себя он так же, но учтите, что <button> внутри формы по умолчанию имеет type="submit".

У кнопок отправки (и <input>, и <button>) есть атрибуты, которые переопределяют настройки самой формы только для этой кнопки: formaction, formmethod, formenctype, formtarget и formnovalidate. Классический сценарий — «Опубликовать» и «Сохранить черновик» в одной форме, причём черновик можно сохранить, не заполнив обязательные поля:

<form action="/posts" method="post">
  <input type="text" name="title" required>
  <textarea name="body" required></textarea>

  <input type="submit" value="Опубликовать">
  <input type="submit" value="Сохранить черновик" formaction="/drafts" formnovalidate>
</form>

hidden — невидимое, но не секретное

type="hidden" отправляет значение вместе с формой, но не показывает поле на странице. Типичное применение — CSRF-токен или id редактируемой записи.

<input type="hidden" name="order_id" value="5462">

«Скрытое» здесь значит «не нарисованное», а не «защищённое». Значение видно в исходнике страницы и в DevTools, и его можно поменять перед отправкой. Пароли, цены и права доступа в hidden-поля не кладут, а всё, что пришло из них, сервер перепроверяет.

Шпаргалка по атрибутам

Атрибуты <input> работают не со всеми типами: min у текстового поля или maxlength у даты браузер просто проигнорирует. Ниже — что к чему подходит.

Атрибут Что делает С какими типами
name, value ключ и значение в отправленных данных все (у кнопок value — ещё и текст)
required без значения форма не отправится все, кроме range, color, hidden и кнопок
disabled поле недоступно и не отправляется все
readonly менять нельзя, но значение отправляется текстовые, number, даты
placeholder серая подсказка до ввода text, search, email, url, tel, password, number
minlength, maxlength длина строки в символах text, search, email, url, tel, password
pattern регулярное выражение для всего значения те же шесть текстовых типов
size видимая ширина поля в символах те же шесть текстовых типов
min, max, step границы и шаг значения number, range, все пять типов даты и времени
multiple несколько значений в одном поле email, file
accept фильтр типов файлов в диалоге file
checked отмечен при загрузке checkbox, radio
list связь с <datalist> все, кроме password, checkbox, radio, file, hidden и кнопок
autocomplete подсказка для автозаполнения браузера текстовые, number, даты, range, color, hidden
autofocus фокус в поле при загрузке страницы все
dirname вместе со значением отправляет направление текста (ltr/rtl) текстовые поля, в первую очередь text и search
src, alt, width, height картинка и её размер image

Несколько уточнений к таблице. pattern проверяет значение целиком, как будто выражение уже обёрнуто в ^(?:…)$, поэтому якоря дописывать не нужно. Ещё одна ловушка: современные браузеры компилируют pattern с флагом v, а в этом режиме символы ( ) [ ] { } / - | \ внутри квадратных скобок нужно экранировать. Выражение [0-9 ()-] браузер сочтёт ошибочным и молча отключит проверку, а [0-9 \(\)\-] сработает. autofocus ставят максимум на одно поле на странице, и только если пользователь пришёл именно заполнять форму: прыжок фокуса сбивает тех, кто ходит с клавиатуры и скринридером. Как оформить состояние «поле заполнено неверно» без JavaScript, через :user-invalid, — в статье про современные псевдоклассы.

Что уходит на сервер, а что нет

Самая частая причина фразы «поле не отправляется» — правила формирования данных формы, а не баг:

  • Поле без name не отправляется совсем, даже если в нём есть id и значение. Сервер узнаёт поля только по name.
  • disabled исключает поле из отправки. Нужно показать значение, запретить его править и при этом отправить — берите readonly.
  • Неотмеченные checkbox и radio не отправляются.
  • Нажатая кнопка отправляет свою пару name=value, только если у неё есть name. Остальные кнопки формы ничего не добавляют.
<form>
  <input type="text" value="уйдёт?">                    <!-- нет: без name -->
  <input type="text" name="sku" value="A-17" disabled>  <!-- нет: disabled -->
  <input type="text" name="price" value="49" readonly>  <!-- да: price=49 -->
  <input type="checkbox" name="gift">                   <!-- нет: не отмечен -->
  <input type="hidden" name="currency" value="EUR">     <!-- да: currency=EUR -->
  <button name="action" value="buy">Купить</button>    <!-- да, если нажата -->
</form>

И последнее: встроенная проверка через type, required и pattern нужна для удобства пользователя, а не для безопасности. Её отключают одним атрибутом в DevTools или обходят прямым запросом, поэтому сервер проверяет всё заново.

Итог

  • Начинайте с подходящего type: клавиатура, проверка и виджет достанутся бесплатно, а неизвестный тип в худшем случае станет текстовым полем.
  • number — для величин, с которыми считают. Наборы цифр вроде PIN и номера карты — это text с inputmode="numeric".
  • Значения дат всегда в ISO-формате, независимо от того, что видит пользователь. month и week пока без запасного варианта не обходятся.
  • Без name поле не отправится, disabled тоже, а readonly — отправится.
  • Всё, что проверил браузер, сервер проверяет ещё раз.