Круговая шкала прогресса

Круговая шкала прогресса выглядит наглядно и симпатично, поэтому часто встречается на сайтах для отображения различных индикаторов, где требуется одновременно показать числовое и визуальное значение (рис. 1).

Рис. 1. Круговая шкала

Для создания такой шкалы мы сперва должны превратить элемент <progress> в круг. Это делается довольно просто — устанавливаем ширину и высоту элемента одинаковыми, затем для получившегося квадрата используем свойство border-radius со значением 50%.

progress {
 width: 200px; height: 200px; /* Размеры */
 border-radius: 50%; /* Превращаем в круг */
}

Шкалу значения создаём с помощью конического градиента conic-gradient(), который применяется к свойство background. По умолчанию такой градиент начинается от верхней точки (где у часов расположено число 12) и идёт по часовой стрелке.

background: conic-gradient(red, lightgray);

Здесь цвет по кругу будет плавно переходить от красного цвета к светло-серому. Но нам требуется сделать резкий, а не плавный переход, поэтому мы начинаем с красного цвета, затем он идёт до 120° и от этого же значения начинается светло-серый цвет, который идёт до конца.

background: conic-gradient(red, red 120deg, lightgray 120deg, lightgray);

В коническом градиенте положение цвета задаётся в градусах от 0 до 360deg, у нас же для <progress> обычно используется значение от 0 до 100. Так что необходимо перевести одно значение в другое с помощью следующей формулы:

Угол= значение <progress>×360deg 100

Стили не могут использовать для вычислений значение атрибута value, поэтому мы его дублируем в атрибуте style и переменной --p.

<progress value="75" max="100" style="--p:75"></progress>

В CSS для вычисления угла используем функцию calc().

progress {
 width: 200px; height: 200px; /* Размеры */
 border-radius: 50%; /* Превращаем в круг */
 --a: calc((var(--p) * 360deg) / 100); /* Переводим в градусы */
 background: conic-gradient(red, red var(--a), lightgray var(--a), lightgray);
}

Осталось скрыть шкалу значений через свойство visibility со значением hidden.

progress::-moz-progress-bar {
 visibility: hidden;
}
progress::-webkit-progress-bar {
 visibility: hidden;
}

Вот как выглядит код на этом этапе (пример 1).

Пример 1. Использование конического градиента

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> progress { --s: 200px; --a: calc((var(--p) * 360deg) / 100); /* Переводим в градусы */ width: var(--s); height: var(--s); /* Размеры */ border-radius: 50%; /* Превращаем в круг */ background: conic-gradient(#3c82f5, #3c82f5 var(--a), #dbeafe var(--a), #dbeafe); } progress::-webkit-progress-bar { visibility: hidden; /* Прячем в Chrome */ } progress::-moz-progress-bar { visibility: hidden; /* Прячем в Firefox */ } </style> </head> <body> <progress value="75" max="100" style="--p:75"></progress> </body> </html>

Следующий шаг — наложение сверху белого круга для создания окружности и отображение значения в процентах. Для этого можно использовать псевдоэлементы ::after и ::before, как это показано в примере 2.

Пример 2. Использование псевдоэлементов

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> progress { --s: 200px; /* Размер шкалы */ --w: 20px; /* Толщина линии */ --a: calc(((var(--p) * 360) / 100) * 1deg); /* Переводим в градусы */ width: var(--s); height: var(--s); border-radius: 50%; /* Превращаем в круг */ background: conic-gradient(#3c82f5, #3c82f5 var(--a), #dbeafe var(--a), #dbeafe); position: relative; /* Относительное позиционирование */ } progress::before { content: ''; /* Пустой псевдоэлемент */ position: absolute; /* Абсолютное позиционирование */ width: calc(var(--s) - 2 * var(--w)); /* Ширина */ height: calc(var(--s) - 2 * var(--w)); /* Высота */ background: #fff; /* Белый фон */ left: var(--w); top: var(--w); /* Сдвигаем в центр */ border-radius: 50%; /* Превращаем в круг */ } progress::after { content: attr(value) '%'; /* Выводим значение атрибута value */ position: absolute; /* Абсолютное позиционирование */ left: 50%; top: 50%; /* Сдвигаем в центр */ transform: translate(-50%, -50%); /* Смещаем на половину размера */ font-size: 2rem; /* Размер текста */ } progress::-webkit-progress-bar { visibility: hidden; /* Прячем в Chrome */ } </style> </head> <body> <progress value="75" max="100" style="--p:75"></progress> </body> </html>

Результат данного примера в браузере Chrome показан на рис. 2.

Рис. 2. Круговая шкала в Chrome

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

<div class="progress-bar" role="progressbar" aria-valuenow="75" aria-valumax="100" style="--p:75">
 <div class="progress-value">75%</div>
</div>

Теперь вместо ::before применяем стиль к элементу с классом progress-value (пример 3). Для разнообразия, выравнивание окружности и текста делается с помощью флексов вместо позиционирования. При этом код CSS получается проще и нагляднее.

Пример 3. Использование <div>

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> .progress-bar { --s: 200px; /* Размер шкалы */ --w: 20px; /* Толщина линии */ --a: calc(((var(--p) * 360) / 100) * 1deg); /* Переводим в градусы */ width: var(--s); height: var(--s); /* Размеры */ border-radius: 50%; /* Превращаем в круг */ background: conic-gradient(#3c82f5, #3c82f5 var(--a), #dbeafe var(--a), #dbeafe); } .progress-value { width: calc(var(--s) - 2 * var(--w)); /* Ширина */ height: calc(var(--s) - 2 * var(--w)); /* Высота */ background: #fff; /* Белый фон */ border-radius: 50%; /* Превращаем в круг */ font-size: 2rem; /* Размер текста */ } /* Выравнивание по центру */ .progress-bar, .progress-value { display: flex; justify-content: center; align-items: center; } </style> </head> <body> <div class="progress-bar" role="progressbar" aria-valuenow="75" aria-valumax="100" style="--p:75"> <div class="progress-value">75%</div> </div> </body> </html>

Итоги

  • Круговая шкала прогресса создаётся с помощью конического градиента conic-gradient(). Для создания окружности сверху шкалы накладывается белый круг уменьшенного радиуса.
  • В коническом градиенте положение цвета задаётся в градусах от 0 до 360deg, а для <progress> обычно используется значение от 0 до 100. Перевод в градусы делается через стилевую функцию calc().
  • Firefox и Safari для элемента <progress> не поддерживают псевдоэлементы ::before и ::after и для их работы заменяем <progress> на <div>.

Перейти к заданиям

Автор: Влад Мержевич
Последнее изменение: 18.07.2025

Создайте круговую шкалу прогресса, чтобы она выглядела одинаково в браузерах Chrome и Safari, как показано на рис. 1.

Рис. 1

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> .progress-bar { --s: 200px; --w: 20px; --a: calc(((var(--p) * 360) / 100) * 1deg); width: var(--s); height: var(--s); border-radius: 50%; background: conic-gradient(#f59421, #f59421 var(--a), #ede9e0 var(--a), #ede9e0); } .progress-value { width: calc(var(--s) - 2 * var(--w)); height: calc(var(--s) - 2 * var(--w)); background: #fff; color: #2e3f53; border-radius: 50%; font-size: 2rem; } .progress-bar, .progress-value { display: flex; justify-content: center; align-items: center; } </style> </head> <body> <div class="progress-bar" role="progressbar" aria-valuenow="30" aria-valumax="100" style="--p:30"> <div class="progress-value">30%</div> </div> </body> </html>

Создайте круговую шкалу прогресса, чтобы она выглядела одинаково в браузерах Chrome и Safari, как показано на рис. 1.

Рис. 1

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> .progress-bar { --s: 200px; --w: 20px; --c1: #71c317; --c2: #fd880e; --c3: #ede9e0; --a: calc(((var(--p) * 360) / 100) * 1deg); width: var(--s); height: var(--s); border-radius: 50%; background: conic-gradient(var(--c1), var(--c2) var(--a), var(--c3) var(--a), var(--c3)); } .progress-value { width: calc(var(--s) - 2 * var(--w)); height: calc(var(--s) - 2 * var(--w)); background: #fff; color: #2e3f53; border-radius: 50%; font-size: 2rem; } .progress-bar, .progress-value { display: flex; justify-content: center; align-items: center; } </style> </head> <body> <div class="progress-bar" role="progressbar" aria-valuenow="80" aria-valumax="100" style="--p:80"> <div class="progress-value">80%</div> </div> </body

Создайте круговую шкалу прогресса, чтобы она выглядела одинаково в браузерах Chrome и Safari, как показано на рис. 1.

Рис. 1

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> body { --c-bg: #1e252f; background-color: var(--c-bg); } .progress-bar { --s: 200px; --w: 30px; --c1: #8c3022; --c2: #ffc835; --a: calc(((var(--p) * 360) / 100) * 1deg); width: var(--s); height: var(--s); border-radius: 50%; border: 2px solid var(--c1); background: conic-gradient(var(--c2), var(--c2) var(--a), transparent var(--a), transparent); } .progress-value { width: calc(var(--s) - 2 * var(--w)); height: calc(var(--s) - 2 * var(--w)); background-color: var(--c-bg); color: #eeecf6; border-radius: 50%; border: 2px solid var(--c1); font-size: 2rem; } .progress-bar, .progress-value { display: flex; justify-content: center; align-items: center; } </style> </head> <body> <div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valumax="100" style="--p:60"> <div class="progress-value">60%</div> </div> </body> </html>

Создайте круговую шкалу прогресса, чтобы она выглядела одинаково в браузерах Chrome и Safari, как показано на рис. 1.

Рис. 1

<!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>progress</title> <style> .progress-bar { --s: 200px; --w: 30px; --c1: #cb3638; --c2: #dfd8ce; --a: calc(((var(--p) * 360) / 100) * 1deg); width: var(--s); height: var(--s); border-radius: 50%; background: conic-gradient(var(--c1), var(--c1) var(--a), var(--c2) var(--a), var(--c2)); } .progress-value { width: calc(var(--s) - 2 * var(--w)); height: calc(var(--s) - 2 * var(--w)); background-color: #bcb0a4; color: #fff; border-radius: 50%; border: 6px solid #fff; font-size: 2rem; font-weight: bold; } .progress-bar, .progress-value { display: flex; justify-content: center; align-items: center; } </style> </head> <body> <div class="progress-bar" role="progressbar" aria-valuenow="40" aria-valumax="100" style="--p:40"> <div class="progress-value">40%</div> </div> </body> </html>