
Все разработчики знают о теге <input>, это рабочая лошадка веба.
Но что такое <output>? Большинство его никогда не касались. Кто-то даже не подозревает о его существовании.
И очень жаль, ведь этот тег решает проблему, которую мы годами пытались решить связкой <div> и ARIA: динамические результаты, по умолчанию объявляемые программам для чтения экрана.
Этот тег уже много лет находится в спецификации, но почему-то скрывается у всех на виду.
Вот, что говорится в спецификации HTML5:
Элемент
<output>представляет результат вычислений, выполняемых приложением, или результат действия пользователя.
В дереве accessibility он сопоставлен с role="status". Проще говоря, он объявляет о своём значении при его изменении, если уже имеет aria-live="polite" aria-atomic="true".
На практике это означает, что обновления не прерывают пользователя. Они считываются вскоре после действий, и при этом сообщается обо всём контенте, а не только об изменившейся части. При необходимости можно переопределить это поведение, задав собственные свойства ARIA.
Пользоваться им крайне просто:
<output>Здесь находится ваше динамическое значение</output>
Вот и всё. Встроенная поддержка специальных возможностей. Не нужно запоминать никаких атрибутов. Только сам HTML, делающий ровно то, что и всегда должен делать.
Мой момент открытия
Я обнаружил <output> в accessibility-проекте с многоэтапной формой. Форма обновляла оценку риска в процессе изменения значений полей. В браузере она выглядела идеально, но пользователи программ для чтения экрана понятия не имели, что оценка обновляется.
Мы устранили проблему добавлением ARIA live region. Но я всегда считал, что в первую очередь следует использовать семантический HTML, а live region часто похожи на патч.
Тогда я начал изучать спецификацию и обнаружил <output>. Он понимает формы, не требуя их, и нативным образом объявляет об их изменениях. Оказалось, что самое простое решение проблемы всё это время скрывалось в спецификации.
Почему же мы его не используем?
Потому что мы о нём забыли. В большинстве туториалов о нём ничего не говорится. Он не выглядит, как нечто привлекательное. Когда я поискал по публичным репозиториям GitHub, то практически ни разу не встретил его.
Похоже, о нём не помнят и разработчики паттернов библиотек компонентов. Из-за этого возникает цикл обратной связи: если никто не обучает тегу, то им никто не пользуется.
Что нужно знать
Как и у <label>, у <output> есть атрибут for="". В нём мы через пробелы перечисляем id всех элементов <input>, от которых зависит результат:
<input id="a" type="number"> +
<input id="b" type="number"> =
<output for="a b"></output>
Для большинства пользователей визуально ничего не изменится. Но в дереве accessibility это создаст семантическую связь, позволяющую пользователям специальных возможностей соединять input с вычисляемым результатом.
Этот тег не требует <form>. Можно использовать его везде, где динамический текст страницы обновляется в зависимости от пользовательского ввода.
По умолчанию <output> встроен, поэтому обычно нужно стилизовать его под свою структуру страницы, как мы делаем это с <span> или <div>.
А поскольку тег добавлен в спецификацию ещё в 2008 году, он замечательно поддерживается во всех браузерах и программах для чтения экрана. Также он отлично взаимодействует с любыми JavaScript-фреймворками, например с React и Vue.
Дополнение: выяснилось, что некоторые программы для чтения экрана не обновляют изменения в теге, поэтому, вероятно, стоит явно указывать атрибут role, пока ситуация с поддержкой не улучшится: <output role="status">.
Стоит также отметить, что <output> предназначен для результатов, связанных с пользовательским вводом и действиями, а не с глобальными уведомлениями наподобие всплывающих сообщений. Такие уведомления лучше обрабатывать при помощи role="status" или role="alert" в обобщённом элементе, потому что они представляют системную обратную связь, а не вычисляемый вывод.
Как же это выглядит на практике?
Примеры из реальных проектов
Лично я использовал <output> во многих реальных проектах:
Простое приложение-калькулятор
Во время недавнего 20-минутного челленджа по кодингу я использовал <output> для отображения результатов вычислений. Программа для чтения экрана объявляла каждый результат при обновлении без добавления каких-либо ARIA role. И не нужно никаких хаков.
Форматирование ползунка диапазона
В Volvo Cars мы отображаем удобные версии значений ползунков. Внутри ползунок может хранить 10000, а вывод показывать 10,000 miles/year. Мы обернули ползунок и <output> в контейнер с role="group" и общую метку, создав связный компонент React:
<div role="group" aria-labelledby="mileage-label">
<label id="mileage-label" htmlFor="mileage">
Annual mileage
</label>
<input
id="mileage"
name="mileage"
type="range"
value={mileage}
onChange={(e) => setMileage(Number(e.target.value))}
/>
<output name="formattedMileage" htmlFor="mileage">
{mileage.toLocaleString()} miles/year
</output>
</div>
Обратная связь валидации форм
Я выяснил, что индикаторы надёжности пароля и сообщения валидации в реальном времени замечательно работают с <output>.
<label for="password">Password</label>
<input type="password" id="password" name="password">
<output for="password">
Password strength: Strong
</output>
Вывод вычисляется на сервере? Никаких проблем.
Тег <output> вписывается в даже современные паттерны, в которых получаются цены из API, отображается расчёт налогов или генерируемые на сервере рекомендации.
В примере ниже калькулятор стоимости доставки обновляет тег <output>, сообщая пользователям о том, когда стоимость вычислена:
export function ShippingCalculator() {
const [weight, setWeight] = useState("");
const [price, setPrice] = useState("");
useEffect(() => {
if (weight) {
// Получаем с сервера стоимость доставки на основании веса посылки
fetch(`/api/shipping?weight=${weight}`)
.then((res) => res.json())
.then((data) => setPrice(data.price));
}
}, [weight]);
return (
<form>
<label>
Package weight (kg):
<input
type="number"
name="weight"
value={weight}
onChange={(e) => setWeight(e.target.value)}
/>
</label>
<output name="price" htmlFor="weight">
{price ? `Estimated shipping: $${price}` : "Calculating..."}
</output>
</form>
);
}
Качество гарантируется
Есть что-то приятное в том, чтобы использовать нативный элемент HTML для того, для чего он и был придуман, особенно если он повышает accessibilty интерфейса, требуя при этом меньше кода.
Наверно, <output> — самый большой секрет HTML, и обнаружение подобных сокровищ демонстрирует, как много полезного можно найти в спецификации.
Иногда лучший инструмент для задачи — тот, о существовании которого вы не знали.
Дополнение: как всегда великолепный Боб Рудис написал страницу с работающими примерами для моего поста. Она находится здесь: https://rud.is/drop/output.html
Комментарии (3)

JerryI
17.10.2025 12:36Было бы здорово, если бы браузер учитывал такой тег в оптимизации. Типа ага, там будет часто меняющееся содержимое...

AlexMih
17.10.2025 12:36Потому что мы о нём забыли
Это то, что я вижу вокруг во многих стандартах IT, и это меня пугает. Стандарты настолько раздуты и усложнены, что уже недоступны для полного понимания одним человеком, а многие подразделы фактически мертвы. Неужели нам теперь придется специализироваться в подразделах языка разметки - вот специалист по формам, вот по таблицам, а вот по скругленным тоненьким рамкам? Но это же абсурд. Ведь, если вдуматься, задача форматирования контента на экране на самом деле не настолько сложна.
В идеальном мире я бы хотел, чтобы следующий стандарт языка разметки, условный HTML+CSS 6.0, был бы радикально меньше и лаконичнее существующих. Интересно, повернет ли когда-нибудь эволюция в эту сторону, или доведет до того что все рухнет от сложности?
patyupin
Прикольно