Круговая шкала прогресса выглядит наглядно и симпатично, поэтому часто встречается на сайтах для отображения различных индикаторов, где требуется одновременно показать числовое и визуальное значение (рис. 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. Так что необходимо перевести одно значение в другое с помощью следующей формулы:
Стили не могут использовать для вычислений значение атрибута 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