Элемент progress

При разработке сайтов и веб-приложений часто появляется необходимость информировать пользователя о процессе выполнения его запроса или задачи: загрузки файла, проигрывания видео или импортирования данных.

В HTML5 описан элемент, который должен упростить нам жизнь: элемент <progress>, единственная задача которого как раз и состоит в отображении прогресса выполнения задачи.

Лучше всего он описан в спецификации HTML5:

Элемент <progress> представляет прогресс выполнения задачи.

Сама задача на данный момент нас не интересует, в отличии от отображения хода её выполнения.

Атрибуты

Для элемента <progress> в спецификации обозначены четыре атрибута: max, value, position и label. Перед тем как приступить к поочерёдному разбору этих атрибутов, несколько важных примечаний о них:

А сейчас давайте более внимательно рассмотрим каждый атрибут:

Max

Атрибут max — это число с плавающей запятой, которое обозначает какой объем работы должен быть выполнен в общем для завершения задачи. Значение по умолчанию — 1.0.

Value

Это число с плавающей запятой, которое представляет текущий прогресс выполнения задачи. Его значение должно быть больше или равно 0.0 и меньше или равно 1.0 или меньше или равно значению атрибута max, если он указан.

Position

Этот атрибут доступен только для считывания. Он возвращает текущее состояние элемента <progress>. Его значение равно значению атрибута value деленному на значение атрибута max для определённого индикатора прогресса и -1 для неопределённого индикатора прогресса (так как текущее состояние не может быть рассчитано точно).

Label

Этот атрибут также доступен только для считывания, он возвращает список меток label для элемента <progress> (если они есть в наличии).

Примеры

Теперь давайте рассмотрим примеры применения элемента <progress>, а также как его можно обновлять с помощью JavaScript.

Простой неопределённый индикатор прогресса

<progress id='p'></progress>

Поскольку мы понятия не имеем сколько времени потребуется на выполнение задачи, браузер просто будет отображать индикатор прогресса пока задача не будет завершена и мы не спрячем индикатор прогресса, либо не заменим его сообщением «задача выполнена».

Простой определённый индикатор прогресса

<progress id='p' max='70'><span>0</span>%</progress>

И JavaScript для его обновления:

var pBar = document.getElementById('p');
var updateProgress = function(value) {
  pBar.value = value;
  pBar.getElementsByTagName('span')[0].innerHTML = Math.floor((100 / 70) * value);
}

Обратите внимание, что в этом примере 70 — это максимальное значение которое может принимать индикатор прогресса, потому обращение к updateProgress будет иметь значение между 0 и 70. Кроме того, значение также отображается в элементе <progress> как простая строка с процентами для пользователей старых версий браузеров.

Использование <progress> с видео в HTML5

Хорошим примером использования элемента <progress> служит видео в HTML5, где индикатор прогресса информирует пользователя о том, какая часть видео уже произведена. Я не буду приводить весь код, только необходимую часть HTML и JavaScript.

У нас есть элемент <video> с «v» в качестве id.

<progress id='p' max='100' value='0'><span>0</span>% проиграно</progress>

Используйте следующий JavaScript:

var video = document.getElementById('v');
var pBar = document.getElementById('p');
video.addEventListener('timeupdate', function() {
  var percent = Math.floor((100 / video.duration) * video.currentTime);
  pBar.value = percent;
  pBar.getElementsByTagName('span')[0].innerHTML = percent;
}, false);

В JavaScript используется событие timeupdate, которое постоянно инициируется в процессе проигрывания видео. Значение конвертируется в процентное число на основе duration (полная длина) и currentTime (текущая точка в видео).

Использование <progress> для File API

Ещё один полезный пример: использование элемента <progress> для File API. Опять же, в примере не полный код, он предполагает наличие формы для загрузки файла и кнопки «загрузить», элемента <progress> и кода для чтения файла. Непосредственно в самой спецификации есть неплохие примеры.

var p = document.getElementById('p');
reader.addEventListener('loadstart', function(evt) {
  if (evt.lengthComputable) p.max = evt.total;
}, false);
reader.addEventListener('progress', function(evt) {
  if (evt.lengthComputable) p.value = evt.loaded;
}, false);

Здесь событие loadstart используется чтобы задать атрибут max для элемента <progress>, затем с помощью события progress обновляется атрибут value для элемента <progress>.

Поддержка браузерами

На сегодняшний день элемент <progress> довольно неплохо поддерживается большинством браузеров. Только в Safari он поддерживается с версии 6+ (что исключает Safari под Windows, так как для него пока только версия 5.1) и в версии 10+ в Internet Explorer.

Стилизация

Как и для других элементов такого типа, у каждого браузера есть свой вариант стилизации для элемента <progress>. Вы, однако, можете в некоторой степени изменить её, используя несложный CSS.

Как правило, стиль по умолчанию предполагает элемент со скругленными уголками, серым фоном и зеленым градиентом собственно для шкалы прогресса.

Скриншот1

Стилизация элемента <progress> по умолчанию в Firefox 18.0.2.

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

progress {
  color: #0063a6;
  font-size: .6em;
  line-height: 1.5em;
  text-indent: .5em;
  width: 15em;
  height: 1.8em;
  border: 1px solid #0063a6;
  background: #fff;
}

Он, однако, не поможет изменить цвет самого индикатора прогресса, который останется зеленым. Это можно изменить в Firefox, Internet Explorer 10, Chrome и Safari с помощью различных методов, описанных ниже.

Firefox

Всё что нужно добавить это:

progress::-moz-progress-bar { background: #0063a6; }

и в Firefox будет отображаться нужный нам цвет.

Скриншот2

Вид индикатора прогресса в Firefox 18.0.2 после дополнительной стилизации.

Chrome и Safari

Для Chrome и Safari следует использовать progress::-webkit-progress-value чтобы указать цвет индикатора прогресса и progress::-webkit-progress-bar чтобы изменить фоновый цвет самого элемента <progress>.

progress::-webkit-progress-bar { background: #fff; }
progress::-webkit-progress-value { background: #0063a6; }

Обновление, добавлено 13 февраля, 2013 года

Разработчики Opera только что объявили о переходе на движок WebKit, так что в конце концов правила стилизации WebKit будут работать и в Opera тоже.

Internet Explorer 10

Вообще то приведённого выше кода CSS будет достаточно чтобы задать стиль для элемента <progress> в IE10, но нужно отметить что этот браузер под цветом элемента <progress> понимает цвет индикатора прогресса.

Я загрузил несколько рабочих примеров определённых и неопределённых индикаторов прогресса чтобы вы могли на них взглянуть.

Итог

Элемент <progress> может показаться очень похожим на элемент <meter>, который также был введён в HTML5, но его можно считать более узкоспециализированным вариантом этого элемента, который используется только для отображения прогресса выполнения задачи. Это стоит помнить когда придётся выбирать между ними.

Учитывая хорошую поддержку браузерами, в подходящих случаях определённо стоит использовать элемент <progress>, но нужно обеспечить текстовый резервный контент для старых версий браузеров.