Тег button (от английского button, «кнопка») создаёт кнопку, внутри которой можно записать не только текст, но и разметку: значок, картинку, выделенное слово. Это парный тег: закрывающий </button> обязателен. Без атрибута type кнопка внутри формы отправляет её, поэтому кнопку, которая ничего не отправляет, записывают с type="button".
Кнопка чаще всего работает вместе с тегом form и полями input. У input тоже есть кнопки, их отличия показаны в разделе с вопросами, а подробный разбор есть в уроке «Кнопка с содержимым в HTML: чем button отличается от input type=submit».
<form action="/send">
<input name="q">
<button>Найти</button>
</form>
В этой статье
- Тег button в HTML: что это, блочный он или строчный
- Атрибут type тега button: submit, button и reset
- Что можно записать внутри button и что нельзя
- Атрибуты name и value у button: какая кнопка отправила форму
- Атрибуты formaction, formmethod и form у кнопки
- Кнопка по умолчанию: что нажимает клавиша Enter в поле
- Отключённая кнопка: disabled и aria-disabled
- Кнопка-ссылка: button, форма или тег a
- Кнопка без JavaScript: popovertarget, command и commandfor
- CSS для кнопки button: сброс стилей и состояния
- Доступное название кнопки: текст, aria-label и aria-pressed
- Тег button и JavaScript: click, клавиатура и submitter
- Вопросы про тег button: отличие от input и двойная отправка
- Частые ошибки с тегом button
Тег button в HTML: что это, блочный он или строчный
Тег button строчный: по умолчанию его display равен inline-block, поэтому кнопки встают в одну строку, как слова в тексте. Блочной кнопку делает только display: block. Ширина зависит от надписи, а длинная надпись переносится на следующую строку, и кнопка растёт по высоте. На самой кнопке работают display: flex и display: grid, это удобно для значка рядом с текстом. Шрифт кнопка не наследует от страницы: у неё свой системный шрифт, поэтому в стилях пишут font: inherit.
<button>Первая</button>
<button>Вторая</button>
Пример: размеры, перенос и display
Выберите запись: под результатом вычисленный display, размеры и стоят ли кнопки в одной строке.
Атрибут type тега button: submit, button и reset
Атрибут type принимает три значения. Значение submit отправляет форму, оно же действует по умолчанию. Значение reset возвращает поля к значениям из разметки. Значение button ничего не делает само и нужно скрипту. Неизвестное значение и устаревшее menu браузер читает как submit. Кнопка вне формы с type="submit" ничего не отправляет: у неё нет формы. Подробнее о типе по умолчанию написано в уроке «Тип кнопки в HTML по умолчанию: button без type».
<button type="submit">Отправить</button>
<button type="button">Показать</button>
<button type="reset">Сбросить</button>
Пример: что делает кнопка с разным type
Выберите значение, измените текст в поле и нажмите кнопку: под результатом событие и данные.
Что можно записать внутри button и что нельзя
Внутри button допустимо строчное содержимое: текст, span, strong, img, svg. Недопустимы другие интерактивные элементы (a со ссылкой, input, вторая кнопка) и блоки вроде div: по правилам HTML внутри кнопки пишут только строчное содержимое. Браузер блок и ссылку не уберёт, но клик получится неоднозначным. Вторая кнопка внутри первой не вкладывается: она закрывает первую, и получаются две соседние кнопки.
<button>
<img src="cart.svg" alt="">
<span>В корзину</span>
</button>
Пример: что остаётся внутри кнопки
Выберите запись: под результатом сколько кнопок получилось и допустима ли запись.
Атрибуты name и value у button: какая кнопка отправила форму
Атрибут name задаёт название, под которым кнопка попадает в данные формы, а value задаёт значение. В данные входит только та кнопка, которой отправили форму: остальные не учитываются. Это позволяет различать действия: у Сохранить и Удалить один name и разные value, а сервер смотрит, какое пришло. Кнопка без name в данные не входит, а кнопка с name без value даёт пустое значение. В отличие от input, надпись кнопки и её value никак не связаны.
<button name="act" value="save">Сохранить</button>
<button name="act" value="del">Удалить</button>
Пример: какие данные уходят от кнопки
Выберите запись и нажмите кнопку: под результатом данные формы вместе с нажатой кнопкой.
Атрибуты formaction, formmethod и form у кнопки
Кнопка отправки может переопределить параметры формы. Атрибут formaction меняет адрес, formmethod метод, formenctype кодирование, formtarget окно ответа, а formnovalidate отключает проверку полей для этой кнопки. Так одна форма получает несколько действий: «Найти» и «Сохранить черновик». Атрибут form привязывает кнопку к форме по id, если кнопка записана вне формы, как и атрибут form у поля.
<form action="/send" method="get">
<input name="q">
<button>Найти</button>
<button formaction="/draft" formmethod="post">Черновик</button>
</form>
Пример: куда уйдёт форма от разных кнопок
Выберите атрибут и нажмите кнопки: под результатом адрес, метод и данные.
Все атрибуты кнопки собраны в таблице, устаревшие и нестандартные отмечены отдельно.
| Атрибут | Статус | Что делает | Пример записи |
|---|---|---|---|
type | актуален | Поведение: submit, button или reset | type="button" |
name | актуален | Название кнопки в данных формы | name="act" |
value | актуален | Значение кнопки в данных формы. Надписью не становится | value="save" |
disabled | актуален | Отключает кнопку: нет нажатия и фокуса | disabled |
form | актуален | Привязка к форме по id, если кнопка вне формы | form="order" |
formaction | актуален | Свой адрес отправки. Только для submit | formaction="/draft" |
formmethod | актуален | Свой метод: get, post или dialog | formmethod="post" |
formenctype | актуален | Своё кодирование данных | formenctype="text/plain" |
formtarget | актуален | Окно для ответа сервера | formtarget="_blank" |
formnovalidate | актуален | Отправка без проверки полей | formnovalidate |
autofocus | актуален | Переводит фокус на кнопку при загрузке страницы | autofocus |
popovertarget | актуален | Открывает или закрывает элемент с popover по id | popovertarget="menu" |
popovertargetaction | актуален | Действие для поповера: show, hide или toggle | popovertargetaction="hide" |
command, commandfor | актуален | Команда для dialog или поповера: show-modal, close, toggle-popover | command="show-modal" |
autocomplete | нестандартный | Не входит в стандарт, действует не везде | autocomplete="off" |
type="menu" | устарел | Браузер читает как submit | type="menu" |
Кнопка по умолчанию: что нажимает клавиша Enter в поле
Нажатие Enter в поле формы вызывает кнопку по умолчанию. Это первая кнопка отправки в порядке кода: type="button" и reset не считаются. Браузер вызывает на ней событие click, а затем отправляет форму. Если эта кнопка отключена, Enter не отправит форму, даже когда после неё есть рабочая кнопка. Если кнопок отправки нет, а полей одно, форма всё равно отправится, а при двух полях нет. Общие правила отправки описаны в разделе про отправку по Enter у формы.
<form>
<input name="q">
<input name="w">
<button type="button">А</button>
<button>Б</button>
</form>
Пример: какая кнопка нажимается при Enter
Выберите запись и нажмите Enter в поле: под результатом события click и submit.
Отключённая кнопка: disabled и aria-disabled
Атрибут disabled отключает кнопку: клик не доходит до обработчиков, вызов click() событий не создаёт, фокус кнопка не принимает. Атрибут aria-disabled="true" только сообщает программе чтения с экрана об отключении, сама кнопка продолжает работать и принимать фокус. Отключённый fieldset отключает все кнопки внутри.
<button disabled>Отправить</button>
<button aria-disabled="true">Отправить</button>
Пример: что проходит через отключённую кнопку
Выберите вариант и нажмите на кнопку: под результатом нажатия, отправки и попытки из скрипта.
Кнопка-ссылка: button, форма или тег a
Для перехода на другую страницу правильный элемент это тег a, а кнопку изображают стилями: у ссылки есть адрес и роль link. Кнопка-ссылка нужна, когда переход связан с действием, например с отправкой формы. Есть три способа без a: форма с method="get", атрибут formaction и скрипт с location.href. Форма работает без JavaScript, но к адресу добавляется знак вопроса. Тег button внутри a и наоборот записывать нельзя: два интерактивных элемента в одном.
<a class="btn" href="/page">Открыть</a>
<form action="/page" method="get">
<button>Открыть</button>
</form>
Пример: четыре способа сделать кнопку-ссылку
Выберите способ и нажмите кнопку: под результатом адрес перехода и замечание. Переход в примере отключён.
Кнопка без JavaScript: popovertarget, command и commandfor
Кнопка открывает окно и поповер без скрипта. Атрибут popovertarget связывает кнопку с элементом, у которого есть атрибут popover. Пара commandfor и command новее и умеет больше: show-modal открывает dialog как модальное окно, close закрывает, toggle-popover переключает поповер. Можно записать и свою команду с префиксом -- и обработать событие command. Команды работают в Chrome и Edge с версии 135, в Firefox с 144 и в Safari с 26.2. В старых браузерах кнопка ничего не сделает, поэтому для важных действий держат запасной путь через скрипт.
<button commandfor="dlg" command="show-modal">Открыть окно</button>
<dialog id="dlg">
Окно.
<button commandfor="dlg" command="close">Закрыть</button>
</dialog>
Пример: открытие окна и поповера без скрипта
Выберите вариант и нажмите кнопку: страница не содержит скрипта, а под результатом состояние элемента.
CSS для кнопки button: сброс стилей и состояния
У кнопки свои стили браузера: серый фон, рамка 2 пикселя, системный шрифт. Чтобы кнопка выглядела как часть страницы, сбрасывают шрифт (font: inherit), цвет, фон и рамку, затем задают свой вид. Состояния задают псевдоклассами: :hover для наведения, :active для нажатия, :focus-visible для фокуса с клавиатуры и :disabled для отключённой кнопки. Курсор-рука cursor: pointer по умолчанию у кнопки не включён. Значок рядом с текстом удобно выстраивать через display: inline-flex и gap.
button {
font: inherit;
padding: 8px 16px;
border: 1px solid #ff6b6b;
border-radius: 8px;
background: #fff1ea;
cursor: pointer;
}
button:focus-visible { outline: 3px solid #1c9e93; }
Пример: сброс стилей и состояния кнопки
Выберите вариант: под результатом шрифт кнопки и страницы, а в варианте с состояниями совпавшие псевдоклассы.
Доступное название кнопки: текст, aria-label и aria-pressed
Роль кнопки button задана тегом, а название берётся из содержимого. Если внутри только значок, названия нет, и программа чтения с экрана объявит просто «кнопка». Название задают через aria-label, title или alt картинки внутри. Атрибут value названия не задаёт. Состояние кнопки-переключателя передают атрибутами aria-pressed и aria-expanded, а роль switch с aria-checked подходит для включения и выключения. Значения этих атрибутов меняет скрипт.
<button aria-label="Закрыть">
<svg width="16" height="16"></svg>
</button>
<button aria-pressed="true">Звук</button>
Пример: откуда берётся название и состояние кнопки
Выберите запись: под результатом откуда берётся название и какое состояние передаётся.
Тег button и JavaScript: click, клавиатура и submitter
Событие click у кнопки срабатывает от мыши, касания и клавиатуры. Клавиша Enter вызывает click при нажатии, а пробел при отпускании. Если внутри кнопки есть вложенный элемент, то event.target может оказаться им, а не кнопкой, поэтому ищут closest("button"). У события submit есть свойство submitter: кнопка, которой отправили форму. Вызов button.click() действует как обычное нажатие.
form.addEventListener("submit", (e) => {
e.preventDefault();
console.log(e.submitter.value);
});
Пример: какие события создаёт кнопка
Выберите вариант и работайте с кнопкой мышью и клавиатурой: под результатом журнал событий.
Вопросы про тег button: отличие от input и двойная отправка
Кнопку часто путают с полем input и нажимают дважды, пока форма отправляется: чем button отличается от input и как не отправить форму дважды.
Чем button отличается от input type="button" и submit?
Надпись кнопки input хранится в value и выводится как обычный текст, разметка и картинки внутри невозможны. Внутри button записывают любое строчное содержимое. Поведение у них одинаковое: тип submit отправляет форму, button ничего не делает, reset сбрасывает. Везде, где нужен значок или свой вид надписи, берут button. Подробнее о типе submit у input написано на странице про тип submit у input.
<button type="button"><b>Жирный</b> текст</button>
<input type="button" value="<b>Жирный</b> текст">
Пример: разметка внутри button и input
Выберите элемент: под результатом что получилось с тегами внутри надписи.
Как не дать отправить форму дважды?
Кнопку отключают в обработчике события submit у формы. Если отключить кнопку в обработчике click, форма вообще не отправится: браузер проверяет отключение после обработчиков, и событие submit не приходит. Обходной путь: отключить кнопку через setTimeout(..., 0).
form.addEventListener("submit", () => {
button.disabled = true;
});
Пример: когда отключать кнопку
Выберите вариант и нажмите кнопку: под результатом, ушла ли форма.
Частые ошибки с тегом button
Ошибки с кнопкой в основном про забытый type и неверное содержимое.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
Кнопка без type внутри формы, а нужно открыть окно | Кнопка отправляет форму, страница перезагружается | Записать type="button" |
Кнопка отправки записана вне form | Нажатие ничего не отправляет | Перенести кнопку в форму или записать form="id" |
Внутри кнопки записан div | Запись недопустима по правилам HTML | Заменить div на span |
Ссылка a внутри кнопки или кнопка внутри a | Два интерактивных элемента в одном, клик неоднозначен | Выбрать один элемент: a для перехода, button для действия |
| Кнопка из одного значка без названия | Программа чтения с экрана объявит просто «кнопка» | Добавить aria-label |
Кнопку отключают в обработчике click | Событие submit не приходит, форма не уходит | Отключать в обработчике submit или через setTimeout |
Вместо disabled записан aria-disabled="true" | Кнопка выглядит отключённой для программы чтения, но продолжает работать | Записать disabled или блокировать действие в скрипте |
| Шрифт кнопки не совпадает с шрифтом страницы | Кнопка не наследует шрифт и выводится системным | Записать font: inherit |
Несколько кнопок с одним name без value | В данные уходит пустое значение, не понять, какая кнопка нажата | Задать каждой кнопке свой value |