При создании веб-сайтов и веб-приложений периодически требуется показать пользователю информацию о ходе выполнения какого-либо запроса или задачи, будь то загрузка файла, воспроизведение видео или импорт данных.
Для этого в HTML5 был введен специальный элемент <progress>, который призван упростить эту задачу для разработчиков. Его еще называют индикатором выполнения или прогресс-баром. Достаточно часто он используется не только с точки зрения html-разметки (она простая) или указания css-свойств, но и с точки зрения динамического управления отображением процесса выполнения задачи, который основан на JavaScript-коде.
В спецификации HTML5 поле деятельности элемента progress определено так:
Элемент progress представляет собой индикатор прогресса выполнения задачи.
То есть вы можете выбрать любую задачу, которая требует определенного времени, и показать пользователю процесс ее прохождения с помощью элемента progress. Например, это может быть изменение времени на прохождение теста, прогресс в чтении статьи или книги по отношению к ее объему.
Краткое содержание статьи:
- Атрибуты тега <progress>
- Поддержка браузерами
- Стили CSS
- Замена элемента progress
- Примеры использования
Атрибуты тега <progress>
Для тега<progress> в спецификации указаны такие атрибуты: max и value. Использование элемента несколько различается в зависимости от того, какие из атрибутов в нем указаны:progress
- Если указан атрибут
value, то элемент<progress>считается определенным, или determinate (т.е. имеет точные пределы). В противном случае он считается неопределенным (indeterminate). В зависимости от наличия этого атрибута разные браузеры по-разному стилизуют прогресс-бар. - Если атрибут
maxне добавлен в тег, то допустимым диапазоном элемента<progress>по умолчанию является от 0,0 до 1,0 включительно. - Рекомендуется всегда добавлять атрибуты
value(текущее значение) иmax(максимальное значение) между тегами в элемент<progress>, чтобы информация по-прежнему была видна пользователям старых браузеров.
Возможные атрибуты тега <progress>:
max- максимальное значение прогресса. Значение по умолчанию - 1.0 (коэффициент, соответствующий 100% выполненной задачи).value- текущее значение прогресса. Его значение должно быть >= 0 и <= 1 (по умолчанию, т.е. некий коэффициент, соответствующий прогрессу выполнения задачи от 0 до 100%) или значению атрибутаmax, если он указан.
Поддержка браузерами
Вы можете убедиться в хорошей поддержке элемента <progress> на сайте caniuse.com. Проблемы есть только в мобильных версиях Safari для iOs, Android 2.1-4.3, а также 6-9 версий Internet Explorer. То есть практически все современные браузеры поддерживают использование этого элемента.
Стили CSS
Со стилизацией все обстоит несколько сложней, т.к. все браузеры имеют свой собственный стиль для элемента <progress>. Однако вы можете переопределить стили в CSS, используя ряд стандартных свойств и ряд псевдоэлементов с вендорными префиксами. И тут есть несколько особенностей:
- Следует отметить, что элемент
progressпо умолчанию имеет стильdisplay: inline-block, поэтому, если вам необходимо изменить его размер в соответствии с размерами какого-либо родительского элемента, можно задать ему свойствоdisplay: block. - Стили необходимо задавать по-разному для элементов
progressс установленным атрибутомvalueи без него. - Для браузеров на различных платформах (webkit или moz), правила для псевдоэлементов нужно указывать отдельно.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
progress { display: block; } /* css-правила для определенного (determinate) элемента progress с атрибутом value */ progress[value] { /* css-правила */ } progress[value]::-webkit-progress-bar { /* css-правила */ } progress[value]::-webkit-progress-value { /* css-правила */ } progress[value]::-moz-progress-bar { /* css-правила */ } /* css-правила для неопределенного (indeterminate) элемента progress без атрибута value */ progress:not([value]) { /* css-правила */ } progress:not([value])::-webkit-progress-bar { /* css-правила */ } progress:not([value])::-webkit-progress-value { /* css-правила */ } progress:not([value])::-moz-progress-bar { /* css-правила */ } |
Давайте посмотрим, как выглядит элемент progress в вашем браузере.
В Инспекторе свойств (F12) браузера вы увидите следующие стили.

Теперь воспользуемся подсказкой, указанной выше, и стилизуем наш прогресс-бар:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<style> progress.styled { display: block; border-radius: 6px; width: 80%; height: 22px; border: 1px solid #e8c00e; } progress.styled::-webkit-progress-bar { background-color: beige; border-radius: 6px; } progress.styled::-webkit-progress-value { background-color: green; background-image: linear-gradient(green, lime); border-radius: 6px; } progress.styled::-moz-progress-bar { background-color: green; background-image: linear-gradient(green, lime); border-radius: 6px; } </style> <body> <p>Определенный (Determinate) прогресс-бар с атрибутами value="50" и max="100":</p> <progress value="50" max="100" class="styled">Determinate</progress> <p>Неопределенный (Indeterminate) прогресс-бар без атрибутов:</p> <progress class="styled">Indeterminate</progress> </body> |
Стилизация элемента progress
Стилизация элемента progress
Определенный (Determinate) прогресс-бар с атрибутами value="50" и max="100":
Неопределенный (Indeterminate) прогресс-бар без атрибутов:
Особенности стилизации <progress> в Chrome, Safari и Firefox
Обратите внимание, что для браузеров Chrome и Safari нам нужно использовать 2 разных псевдоэлемента:
progress::-webkit-progress-value, чтобы указать цвет индикатора выполнения;progress::-webkit-progress-bar, чтобы указать цвет фона самого элемента<progress>:
|
1 2 |
progress::-webkit-progress-bar { background: #fff; } progress::-webkit-progress-value { background: green; } |
Для Firefox нужно указывать все свойства в псевдоэлементе -moz-progress-bar.
Для того чтобы все браузеры отображали ваши стили одинаково, вы можете также добавить такие css-правила:
|
1 2 3 4 5 |
progress { -webkit-appearance: none; -moz-appearance: none; appearance: none; } |
Для Firefox можно также записать строку -moz-orient: vertical и получить вертикальный прогресс-бар.
Замена элемента progress
Элемент progress можно заменить набором div-ов, применяя внутри него разнообразную анимацию. Один из таких примеров вы найдете ниже.
See the Pen fancy progress bar by Sebastian Schepis (@sschepis) on CodePen.
Еще два варианта в 3D виде:
- горизонтальный:
See the Pen Pure CSS Progress by Rafael González (@rgg) on CodePen.
- вертикальный:
See the Pen Pure CSS Bars by Rafael González (@rgg) on CodePen.
Использование замены элемента progress для отображения рейтинга.
See the Pen Reviews Design - #025 of #100Days100Projects by Florin Pop (@FlorinPop17) on CodePen.
Примеры использования элемента progress
Давайте теперь рассмотрим, как мы можем использовать элемент <progress> на страницах, управляя им с помощью JavaScript-кода.
Неопределенный прогресс-бар для отображения процесса загрузки изображения
Загрузку изображений будем выполнять из внешнего источника - сайта unsplash.com, чтобы процесс загрузки был подольше, хотя это весьма условное утверждение при нынешней скорости Интернет-соединений даже на мобильных устройствах. Тег img будем создавать в коде JavaScript.
Для того чтобы протестировать несколько раз загрузку и отображение ее прогресса в элементе <progress>, создадим функцию, которая будет вызываться каждый раз при клике на кнопку "Загрузить изображение". В самой же функции будем отображать спрятанный изначально с помощью атрибута hidden прогресс-бар с id="imgProgress". Изображения будем формировать с помощью ссылки, позволяющей загрузить фото с определенным id и размером с unsplash.com. Соберем несколько таких фото в массив imgArr, указав в качестве его элементов только их id.
При клике на кнопке "Загрузить изображение" мы будем показывать прогресс-бар и сообщение о том, что идет загрузка, а по окончании загрузки (событие img.onload) мы будем их прятать с помощью свойства hidden.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<div class="text-center"> <p><button class="button" onclick="showRandomImg()">Загрузить изображение</button></p> <progress id="imgProgress" hidden></progress> <p id="info"></p> <div id="imgHolder"></div> </div> <script> const imgArr = ['photo-1755796594130-d25977e4951b', 'photo-1757581559865-96f48eb27673', 'photo-1472396961693-142e6e269027', 'photo-1615729947596-a598e5de0ab3', 'photo-1439853949127-fa647821eba0', 'photo-1549399542-7e3f8b79c341', 'photo-1599889959407-598566c6e1f1', 'photo-1552053831-71594a27632d', 'photo-1571035330093-fd93f6321a7b', 'photo-1500916434205-0c77489c6cf7', 'photo-1583458006012-cb6e59c4322a', 'photo-1525431836161-e40d6846e656', 'photo-1515031245064-22453e134337']; let img = new Image(800, 1000); img.alt = "Random Unsplash.com Photo"; function showRandomImg() { imgProgress.hidden = false; info.textContent = 'Идет загрузка изображения ...'; let imgId = imgArr[Math.floor(Math.random() * imgArr.length)]; img.src = 'https://images.unsplash.com/' + imgId + '?crop=faces&fit=crop&w=800&h=1000'; imgHolder.append(img); img.onload = function() { info.textContent = 'Загрузка завершена'; imgProgress.hidden = true; } } </script> |
Нам не нужно в элементе progress указывать атрибут value, т.к. процес загрузки достаточно быстрый.
Попробуйте пример в действии (открыть в новой вкладке):
Увеличение значения определенного прогресс-бара
В примере ниже мы будем увеличивать значение атрибута value определенного прогресс-бара.
|
1 2 3 |
<progress value="0" max="200" id="my-progress-bar"></progress> <label for="my-progress-bar" id="progress-label">0%</label> <p><button class="button" onclick="increaseProgress()">Увеличить значение</button></p> |
Код JavaScript, который управляет элементом <progress>:
|
1 2 3 4 5 6 7 |
var myBar = document.getElementById('my-progress-bar'), labelBar = document.getElementById('progress-label'); let increaseProgress = function() { myBar.value += 10; myBar.innerHTML = myBar.value/2+'%'; myBar.value < 200 ? labelBar.innerHTML = myBar.value/2+'%': (labelBar.innerHTML = '100%. Максимум.', increaseBtn.hidden = true ); } |
Поскольку максимальное значение нашего прогресс-бара max="200", то в функции для получения процентного соотношения мы делим value прогресс-бара на 2.
Пример "вживую":
Используем элемент <progress> при воспроизведении видео
Как правило, в тег <video> в HTML5 добавляют атрибут controls для управления его воспроизведением. Однако у вас может быть видео, которое не имеет такого атрибута, а процесс воспроизведения, тем не менее, хочется отобразить. Вот тут и пригодится элемент <progress>. Его атрибуты value и max будут иметь значения 0 и 100, соответственно, и это мы потом используем в скрипте.
Для всех элементов в разметке мы используем атрибут id для простого обращения к нм в коде JavaScript:
|
1 2 3 |
<progress value="0" max="100" id="video-progress"></progress> <label for="video-progress" id="video-label">0%</label> <p><video src="video/hamster.mp4" id="my-video" controls></video></p> |
Код JavaScript:
|
1 2 3 4 5 6 7 8 |
let videoProgress = document.getElementById('video-progress'), labelVideo = document.getElementById('video-label'), video = document.getElementById('my-video'); video.addEventListener('timeupdate', function() { var percent = Math.floor((100 / video.duration) * video.currentTime); videoProgress.value = percent; labelVideo.textContent = percent +'%'; }); |
В JavaScript мы обрабатываем событие timeupdate, которое постоянно запускается во время воспроизведения видео. В нем мы рассчитываем процентное значение, используя всю продолжительности видео (video.duration) и video.currentTime (текущее время проигрывания видео).
Давайте посмотрим забавное видео и пронаблюдаем за прогрессом его воспроизведения. Заметьте, что когда вы перемещаете ползунок воспроизведения видео, прогресс также увеличивается.
Используем элемент <progress> для загрузки файла с помощью File API
Этот пример связан с использованием элемента<progress> для загрузки файлов, основанной на File API. Вариант кода вы можете посмотреть в спецификации.
Разметка примера:
|
1 2 3 |
<p><progress value="0" max="100" id="progress-file"></progress></p> <form name="fileUploadForm"><input type="file" name="file-input" id="file-input"></form> <div id="file-output"></div> |
Как вы видите, мы используем input type="file" для загрузки txt-файла. Кстати, в js-коде мы будем это проверять.
JavaScript-код примера:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
let barFile = document.getElementById('progress-file'), fileInput = document.getElementById('file-input'), fileOutput = document.getElementById('file-output'); fileInput.onchange = startRead; function startRead() { // получаем информацию о загруженном в input файле var file = fileInput.files[0]; //проверяем, чтобы расширение файла было txt if (file.name.slice(file.name.lastIndexOf('.') + 1) != 'txt') { fileOutput.innerHTML = '<span style="color: red">Допустимо загружать только .txt-файлы!!!</span>'; return false; } else fileOutput.innerHTML = ''; if (file) { barFile.value = 0; getAsText(file); } } function getAsText(readFile) { //создаем переменную-экземпляр класса var reader = new FileReader(); // считываем файл в память в кодировке UTF-8 reader.readAsText(readFile, "UTF-8"); reader.onprogress = updateProgress; reader.onload = loaded; reader.onerror = errorHandler; } function updateProgress(evt) { //имитируем процесс загрузки файла if (evt.lengthComputable) { let i = 0; let progressId = setInterval(function() { i++; barFile.value = i * 10; if (i > 10) clearInterval(progressId); }, evt.total / 300000); } } function loaded(evt) { // Получаем данные из txt-файла var fileString = evt.target.result; //преобразуем переносы строк в txt в перенос строк в html-разметке в виде тега <br> var fileStringChange = fileString.replace(/\r*\n+/g, '<br>'); fileOutput.innerHTML = fileStringChange; } function errorHandler(evt) { if (evt.target.error.name == "NotReadableError") alert('Невозможно прочитать содержимое файла!'); } |
В приведенном коде событие progress используется для обновления атрибута value элемента <progress>, а событие load - для отображения результата чтения данных из txt-файла.
Тестируем пример:
Элемент progress для отображения прогресса чтения статьи
Еще один вариант использования прогресс-бара на странице сайта - это отображение прогресса чтения статьи. Как правило, элемент <progress> в этом случае располагается вверху страницы, обычно до или после меню (он даже может быть добавлен непосредственно в скрипте, как в примере ниже). Когда пользователь читает текст статьи, значение атрибута value увеличивается, и прогресс-бар медлено растет слева направо в виде сплошной полосы нужного вам цвета, который назначается в стилях.
CSS-стили для примера:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
.progress-reading { display: block; position: fixed; left: 0; top: 0; width: 100%; height: 5px; z-index: 9999; -webkit-appearance: none; -moz-appearance: none; appearance: none; border: none; background-color: transparent; } .progress-reading::-webkit-progress-bar { background-color: #fff; } .progress-reading::-webkit-progress-value{ background-color: #2a7fa3; } .progress-reading::-moz-progress-bar { background-color: #2a7fa3; } |
JavaScript-код
Код этого примера написан с использованием jQuery. Вам сначала нужно будет подключить эту библиотеку, указав к ней путь из локальной папки или с CDN, а затем использовать такой код:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<script src="js/jquery.js"></script> <script> (function($) { $('body').prepend('<progress class="progress-reading" value="0"></progress>'); let winHeight = $(window).height(), docHeight = $(document).height(); let max = docHeight - winHeight; $('.progress-reading').attr('max', max); // начальное значение фтрибута value прогресс-бара var value = $(window).scrollTop(); $('.progress-reading').attr('value', value); // обновляем значение value в зависимости от положения прокрутки $(document).on('scroll', function() { value = $(window).scrollTop(); $('.progress-reading').attr('value', value); }); })( jQuery ); </script> |
Пример этого прогресс-бара вы увидите в процессе чтения статьи. Надеюсь, что читая эти строки, вы видите, как элемент <progress> приблизился к правому краю вашего браузера.
Имитация progress bar при чтении статьи
Элемент progress можно имитировать, использовав для этого либо разметку в виде div, либо даже с помощью псевдоэлементов ::before и ::after на чистом CSS. Последний пример вы найдете ниже. В любом случае выбор способа решения задачи остается всегда за вами.
See the Pen Reading Progess Bar CSS only by Elen (@ambassador) on CodePen.
Резюме
Элемент <progress> можно и нужно использовать для отображения процесса загрузки картинок, чтения статьи, времени решения задачи или загрузки файлов на сервер. Его можно стилизовать, используя псевдоэлементы, и управлять им из JavaScript-кода.

Информация - супер! Огромная благодарность.