Тег progress в HTML: что это, value, max и стилизация

Тег progress показывает, сколько работы уже сделано: загрузка файла, шаги анкеты, обработка заказа. Браузер рисует горизонтальную полосу, а доля заполнения задаётся атрибутами value и max. Закрывающий тег </progress> нужен, пропускать его нельзя.

Если задача выполняется и у неё есть конец, нужен progress. Если показывают значение в границах, например заряд батареи или заполненность диска, подходит meter: разница описана в уроке про индикаторы.

HTML
<progress value="70" max="100"></progress>
Результат

Готовая полоса, бегущая загрузка и полоса без значения.

Тег progress в HTML: что это и когда нужен

Полоса показывает долю выполненной работы: чем больше значение, тем шире заполнение. Сам тег ничего не считает и не обновляется: значение меняет скрипт, а браузер перерисовывает полосу. Состояний у полосы два: определённое, когда доля известна, и неопределённое, когда её нет. Вычисленный display равен inline-block, поэтому полоса встаёт в строку рядом с текстом.

HTML
<label>Загрузка
  <progress value="70" max="100"></progress>
</label>

Пример: progress и meter рядом

Результат

Процесс, ожидание и показание прибора.

Атрибуты value и max: доля выполненной работы

Атрибут max задаёт всю работу, а value уже сделанную. Если max не указан, он равен 1, и значение 0.3 означает 30%. Минимум всегда ноль, менять его нельзя. Доля равна value, делённому на max, её же отдаёт свойство position.

HTML
<progress value="4" max="10"></progress>

Пример: как записать долю

Результат

Четыре записи одной идеи.

Неопределённое состояние: progress без value

Если value нет, полоса считается неопределённой: браузер показывает бегущий индикатор, а position равен -1. Это подходит, когда время ожидания неизвестно. Это состояние выбирает псевдокласс :indeterminate. Атрибут value="0" неопределённости не даёт: полоса пустая, но доля известна. Переключают состояние скриптом: убирают атрибут через removeAttribute или записывают число в value.

HTML
<progress max="100"></progress>

Пример: когда полоса неопределённая

Результат

Нет значения, ноль, удаление и возврат.

Неверные value и max: что делает браузер

На неверные числа браузер не сообщает об ошибке, а подбирает значение сам. Лишнее обрезается: value больше max даёт полную полосу, а отрицательное становится нулём. Если value нельзя прочитать как число (пустая строка, abc, 20%), получится пустая полоса, а не неопределённая. Неверный max (ноль, отрицательный, не число) заменяется единицей. Проверка HTML считает такие записи ошибками, поэтому в коде пишут только допустимые числа.

HTML
<progress value="150" max="100"></progress>

Пример: что получается из неверных записей

Результат

Восемь неудачных записей и их результат.

Название полосы: label, aria-label и текст внутри

Полоса сама не говорит, что измеряется, поэтому ей нужно название: через тег label с атрибутом for, через обёртку label или атрибут aria-label. Текст между <progress> и </progress> на странице не виден и названием не служит: его писали для очень старых браузеров.

HTML
<label for="dl">Скачано</label>
<progress id="dl" value="3" max="10"></progress>

Пример: четыре способа дать название

Результат

Три рабочих способа и один нерабочий.

Стилизация тега progress: размер, цвет и вид

Размер задают обычными width и height. Цвет заполнения меняет accent-color, а color на полосу не действует. Свойство writing-mode с вертикальным значением поворачивает полосу. Есть ловушка: стоит задать background или border, и браузер отказывается от родного вида и рисует упрощённую полосу со своими цветами. Для полного контроля сначала снимают родной вид через appearance: none, об этом следующий раздел.

CSS
progress {
  width: 100%;
  height: 24px;
  accent-color: #d94f4f;
}

Пример: размер, цвет и вид

Результат

Шесть правил для одной и той же полосы.

Псевдоэлементы progress: ::-webkit-progress-bar и ::-webkit-progress-value

После appearance: none полоса состоит из двух слоёв: трека и заполнения. Трек красят через ::-webkit-progress-bar, заполнение через ::-webkit-progress-value. В Firefox заполнение задаёт ::-moz-progress-bar. Каждый селектор пишут отдельным правилом: браузер, не знающий псевдоэлемент, отбрасывает правило целиком, а запятая объединила бы их. Скругление, градиент и transition: width на заполнении работают. В неопределённом состоянии заполнения нет, виден только трек.

CSS
progress {
  appearance: none;
  width: 100%;
  height: 14px;
}
progress::-webkit-progress-bar {
  background: #ddd;
  border-radius: 7px;
}
progress::-webkit-progress-value {
  background: #1c9e93;
  border-radius: 7px;
}

Пример: слои полосы

Результат

Пять вариантов оформления.

Тег progress и JavaScript: value и position

Значение меняют свойством value, а долю читают через position: оно только для чтения. Если записать в value больше max, свойство вернёт зажатое число, а в атрибуте останется записанное. Присвоить max = 0 нельзя: атрибут станет единицей. Строка, которую нельзя прочитать как число, вызывает ошибку TypeError.

JavaScript
const bar = document.querySelector("progress");
bar.value = 80;
console.log(bar.position);

Пример: value, position и граничные случаи

Результат

Шесть операций над одной полосой.

Доступность progress: роль progressbar

У тега встроена роль progressbar, и менять её нельзя: проверка HTML отклоняет другие роли. Программа чтения получает название, текущее значение и максимум, а у неопределённой полосы числа нет. Атрибуты aria-valuenow и aria-valuemax перекрывают значения тега, а aria-valuetext добавляет словесное описание. Для региона, который загружается, можно задать aria-busy="true" и снять его после загрузки.

HTML
<label>Скачано
  <progress value="3" max="10"
    aria-valuetext="три из десяти"></progress>
</label>

Пример: что получает программа чтения

Результат

Роль, название и значение в пяти вариантах.

Progress и форма: почему полоса не отправляется

Полоса не относится к полям формы: она не входит в form.elements, не попадает в FormData, и у неё нет свойства form. Группа, которую создаёт тег fieldset, с disabled на неё не действует. Если число нужно отправить, его записывают в поле, например скрытое.

HTML
<form>
  <input name="a" value="1">
  <progress value="3" max="10"></progress>
</form>

Пример: что видит форма

Результат

Список элементов, данные, свойство и отключённая группа.

Атрибуты тега progress

Собственных атрибутов два: value и max. Остальные либо глобальные, либо здесь не работают. Легче всего перепутать min: у ползунка он есть, а у progress минимум всегда ноль.

АтрибутСтатусЧто делаетПример записи
valueдопускаетсяВыполненная работа: число от нуля до maxvalue="70"
maxдопускаетсяВся работа: положительное число, по умолчанию 1max="100"
idглобальныйИдентификатор для label и скриптаid="dl"
classглобальныйКласс для оформленияclass="bar"
titleглобальныйВсплывающая подсказкаtitle="70%"
minне существуетМинимум всегда нольmin="0"
nameне существуетПолоса не отправляется с формойname="p"
formне существуетПолоса не привязывается к формеform="f"
disabledне существуетОтключить полосу нельзяdisabled
typeне существуетВида у полосы нетtype="bar"
roleне допускаетсяРоль встроена: role="none" проверка HTML отклоняет, а role="progressbar" считает лишнимrole="none"

Вопросы про тег progress: процент рядом с полосой и замена div

Рядом с полосой почти всегда хочется показать число, а самодельная полоса из блоков иногда кажется удобнее тега.

Как вывести процент текстом рядом с полосой?

Число записывают в отдельный элемент и обновляют вместе со значением полосы. Для этого подходит тег output: у него встроена роль status, и программа чтения сообщит об изменении. Обычный span тоже работает, но такого сообщения не даёт.

HTML
<progress id="bar" value="40" max="100"></progress>
<output id="pct" for="bar">40%</output>

Пример: span и output

Результат

Кнопка добавляет десять и обновляет оба элемента.

Чем progress лучше div с шириной в процентах?

У div нет роли и значения: для программы чтения это пустой блок. Роль можно добавить через role="progressbar" и три атрибута aria-value*, но их придётся обновлять вручную. Тег progress делает это сам.

HTML
<div class="track" role="progressbar"
  aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
  <div class="fill" style="width: 60%"></div>
</div>

Пример: тег и самодельная полоса

Результат

Три полосы, одинаковые на вид.

Частые ошибки с тегом progress

Одни ошибки связаны с неверными значениями, другие с оформлением, а незакрытый тег — одна из самых частых.

ОшибкаЧто происходитКак исправить
Не закрыть </progress>Весь следующий текст оказывается внутри полосы и пропадает с экранаВсегда писать закрывающий тег
value больше maxПолоса полная, а лишнее значение отрезаноСледить, чтобы value не превышало max
Писать value="20%"Знак процента ломает число, получается пустая полосаЗаписывать число без знака и задать max="100"
Ждать неопределённости от value="0"Полоса пустая, но определённаяУбрать атрибут value совсем
Задать только background и ждать родной видБраузер рисует упрощённую полосу со своими цветамиСначала appearance: none, затем псевдоэлементы
Красить заполнение через colorСвойство на полосу не действуетИспользовать accent-color или псевдоэлементы
Объединять ::-webkit-progress-value и ::-moz-progress-bar запятойБраузер отбрасывает правило целикомПисать отдельное правило для каждого
Не дать полосе названиеПрограмма чтения читает только роль и числаИспользовать label или aria-label
Брать progress для показаний, например зарядаРоль полосы не подходит измерениюИспользовать meter
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×