<progress> и <meter> внешне похожи - оба рисуют горизонтальную полосу, - но означают разное: progress показывает, сколько задачи уже выполнено и сколько осталось, а meter - статичное измерение внутри известного диапазона, необязательно связанное с движением к завершению.
В этом уроке
Первая полоса - обычный progress с конкретным значением. Вторая - progress БЕЗ атрибута value: браузер сам переключает её в "неопределённый" вид (обычно бегущая анимация), потому что процент неизвестен. Третья - meter: значение 15 попало в зону ниже low="20", поэтому браузер подсвечивает шкалу как "плохую" - в отличие от progress, у meter есть понятие "хорошо/плохо" для конкретного значения.
Ход выполнения задачи: progress
<progress> показывает, сколько от задачи уже сделано: атрибут value - текущий прогресс, max - сколько всего нужно сделать (по умолчанию 1). Минимум у progress всегда 0 и не настраивается - атрибута min у него просто нет, в отличие от meter. Если value не указан вовсе, индикатор переходит в НЕОПРЕДЕЛЁННОЕ состояние - это отдельный, стилизуемый через CSS-псевдокласс :indeterminate режим, который браузер обычно показывает бегущей анимацией: подходит, когда процесс идёт, но неизвестно, сколько ещё осталось. Тег имеет встроенную ARIA-роль progressbar, поэтому скринридер сам сообщает об изменении значения, не дожидаясь, пока пользователь перейдёт к элементу.
<progress></progress> - без value: честное "неопределённое" состояние, когда процент неизвестен.
<progress value="0" max="100"></progress> - value="0" выглядит как "0% готово", хотя на самом деле процесс мог ещё даже не начаться и общая длительность неизвестна - для этого случая честнее вообще убрать value.
Шкала измерения: meter
<meter> показывает значение внутри диапазона - у него есть и min, и max (по умолчанию 0 и 1). Меter НЕ предназначен для отображения хода выполнения задачи - для этого есть progress; meter - это скорее заряд батареи, уровень сигнала, температура или оценка. Дополнительные атрибуты low, high и optimum задают зоны значений: если optimum ближе к min, предпочтительна нижняя часть диапазона, если ближе к max - верхняя. Опираясь на эти атрибуты, браузер может визуально подсветить шкалу иначе, когда значение попадает в "плохую" зону.
<meter min="0" max="100" low="20" high="80" optimum="100" value="90"></meter> - заряд батареи 90%, попадает в "хорошую" зону.
<progress min="0" max="100" value="90"></progress> - у progress вообще нет атрибута min, он будет просто проигнорирован; если нужен диапазон измерения, а не прогресс задачи - нужен meter.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Использовать meter для отображения хода выполнения задачи (загрузка, обработка) | meter предназначен для статичного измерения в диапазоне, а не для прогресса к завершению | Для хода выполнения задачи использовать progress |
| Пытаться указать min у progress | У progress минимум всегда 0, атрибута min не существует - он будет просто проигнорирован | Для progress использовать только value и max; диапазон с min - у meter |
| Всегда указывать value у progress, даже когда реальный прогресс неизвестен | Индикатор ложно выглядит как измеримый, хотя на самом деле неизвестно, сколько осталось | Убрать value, чтобы браузер честно показал неопределённое состояние |
| Переписывать HTML-разметку progress/meter при каждом обновлении значения | На реальной странице так не делают - разметка предназначена для начального состояния | Менять значение через JS-свойство элемента (element.value) |
| Не задавать low/high/optimum у meter, ожидая что браузер сам поймёт "хорошо" и "плохо" | Без этих атрибутов зоны не заданы - разница между хорошим и плохим значением не подсвечивается | Явно указывать low/high/optimum, если нужна цветовая индикация |
Шпаргалка
| Тег/атрибут | Что делает |
|---|---|
| <progress> | Ход выполнения задачи (0 до max) - без value переходит в неопределённое состояние |
| <meter> | Измерение в диапазоне (не прогресс) - есть min и max |
| low/high/optimum (у meter) | Задают зоны "плохо/хорошо" - браузер может подсветить цветом |
| :indeterminate (CSS) | Стилизация progress без value отдельно от обычного состояния |
| Нужен "бесконечный" индикатор | progress без атрибута value |
| Нужна шкала батареи/сигнала/оценки | meter, а не progress |
Коротко: отвечаем на вопросы
Чем progress отличается от meter?
progress показывает ход выполнения задачи - сколько сделано и сколько осталось до конца. meter показывает статичное измерение значения внутри диапазона, необязательно связанное с движением к завершению - например, заряд батареи, температуру или оценку. У progress минимум всегда 0, а у meter есть собственные min и max.
Как сделать индикатор загрузки, если неизвестно, сколько осталось?
Нужно просто не указывать атрибут value у progress. Браузер переключит индикатор в неопределённое состояние - обычно это выглядит как бегущая анимация без конкретного процента, честно показывая, что процесс идёт, но сколько он ещё продлится - неизвестно.
Как обновлять значение progress или meter на реальной странице?
Не переписыванием HTML-кода, а через JavaScript: значение меняют напрямую через свойство элемента, например element.value = 70. Разметка в HTML задаёт только начальное состояние, а дальнейшие изменения - задача скрипта.
Можно ли перекрасить полосу progress под дизайн сайта?
Да, через CSS, но обычные свойства вроде background у самого тега работают не полностью - для единого вида во всех браузерах нужны отдельные псевдоэлементы с вендорными префиксами: ::-webkit-progress-bar и ::-webkit-progress-value в Chrome и Safari, ::-moz-progress-bar в Firefox.