Раньше, чтобы сделать круговой прогрессбар, мы страдали с SVG. Мне до сих пор больно заглядывать в инспектор на старых реализациях. Сегодня всё кардинально упростилось.
Современный CSS позволяет собрать сложный, гибкий и красивый круговой прогрессбар буквально на одном div и на одном CSS‑свойстве. И всё это — с отличной браузерной поддержкой.
В этой статье я разберу именно этот приём. Сначала — ключевую идею подхода, затем — возможности кастомизации, после этого добавлю немного визуальной «дороговизны», удобные ручки управления и экспериментальную CSS‑логику. Да‑да, напоследок мы немного попрограммируем на CSS!
Ключевой приём и базовая реализация
Начнём с главного. Вся реализация строится вокруг одного элемента:
<div class="progress"></div>И одного свойства — background-image с несколькими фоновыми изображениями. Ключевой приём заключается в следующем:
верхний фон — радиальный градиент, который формирует форму шкалы;
нижний фон — конический градиент, который отвечает за заполнитель.
Вот базовый CSS:
.progress {
width: 150px;
height: 150px;
background-image:
radial-gradient(
circle,
#222 0% 27%,
transparent 28% 50%,
#222 51%
),
conic-gradient(
#D64E42 0% 60%,
transparent 60%
);
}Радиальный градиент сверху создаёт «бублик» — шкалу с вырезанной прозрачной серединой. Конический градиент снизу заливает сектор круга, то есть управляет заполнителем шкалы.
Важно, здесь используются старые, если не сказать «древние», CSS‑технологии: множественные фоновые изображения, радиальный и конический градиенты с резкими переходами цветов.

Это и есть ключевой приём реализации, который позволяет создать основу прогрессбара. Всё, что будет дальше — это кастомизация и надстройки над этим приёмом.
Кастомизация: ширина шкалы и прозрачность
Одна из приятных особенностей этого подхода — он очень легко кастомизируется.
Ширина шкалы — задаётся параметрами верхнего, радиального, градиента. Для этого играем с позициями цвета в колорстопах:
radial-gradient(
circle,
#222 0% 30%,
transparent 31% 54%,
#222 55%
)Цвет и прозрачность шкалы и заполнителя — задаются параметрами нижнего, конического, градиента. Меняем цвет в первом колорстопе на полупрозрачный — и заполнитель становится полупрозрачным. Меняем цвет во втором колорстопе — и изменяется пустая часть шкалы.
conic-gradient(
rgba(214, 78, 66, 0.6) 0% 60%,
transparent 60%
)Никаких дополнительных элементов, масок или вычислений. Только параметры градиентов.

Хэштег #неколхоз: текстура, рамки и тени
Базовая версия готова, но выглядит довольно колхозно. Добавим немного «дороговизны».
Во‑первых, добавим третий фоновый слой — повторяющийся конически градиент, который создаёт эффект радиальных секций:
repeating-conic-gradient(
rgba(0, 0, 0, 0.3),
rgba(0, 0, 0, 0.2) 4.5%,
transparent 5%
)Во‑вторых, усложним верхний радиальный градиент, добавив промежуточные цвета для тонких рамок:
radial-gradient(
circle,
#222 0% 27%,
#333,
transparent 28% 50%,
#333,
#222 51%
)И в финале — слегка закруглим сам блок прогрессбара и добавим тени:
.progress {
border-radius: 10px;
box-shadow: inset 0 0 1px #666, 0 0 30px black;
}Всё это не влияет на логику компонента — только на внешний вид.

Ручки управления: CSS-переменные
Теперь давайте сделаем прогрессбар удобным для использования в реальных интерфейсах. Для этого добавим CSS‑переменную --progress.
.progress {
--progress: 45;
--corner: calc(1% * var(--progress, 0));
background-image:
radial-gradient(
circle,
#222 0% 27%,
#333,
transparent 28% 50%,
#333,
#222 51%
),
conic-gradient(
#D64E42 0% var(--corner),
transparent var(--corner)
);
}Теперь прогресс задаётся понятным числом от 0 до 100, а CSS сам пересчитывает его в нужный угол.
Можно легко создать несколько экземпляров компонента:
<div class="progress" style="--progress: 15"></div>
<div class="progress" style="--progress: 50"></div>
<div class="progress" style="--progress: 90"></div>
Экспериментальные CSS-фичи: условная логика
А теперь давайте немного заглянем в будущее CSS. В современных версиях Chrome уже можно использовать условную логику с помощью if().
Например, можно менять цвет шкалы в зависимости от значения прогресса:
.progress {
--color: if(
style(--progress <= 33): #D64E42;
style(--progress <= 66): #F5B848;
style(--progress <= 99): #58B473;
else: white;
);
}И использовать этот цвет в градиенте:
conic-gradient(
var(--color) 0% var(--corner),
transparent var(--corner)
)Можно добавить подпись в центре прогрессбара, которая меняется в зависимости от значения прогресса. Добавляем псевдоэлемент, используем if() в свойстве content, чтобы привязать текст подписи к значениям прогресса. Для цвета подписи используем CSS‑переменную --color из родителя.
.progress {
display: flex;
justify-content: center;
align-items: center;
}
.progress::before {
content: if(
style(--progress <= 33): "low";
style(--progress <= 66): "med";
style(--progress <= 99): "high";
else: "go!";
);
color: var(--color);
}Важно: это экспериментальные возможности. Если нужна хорошая поддержка, то используйте JS вместе с классами‑модификаторами.

Вау-эффект: нативная анимация
И напоследок — самое приятное. Этот прогрессбар отлично совместим с нативной CSS‑анимацией.
Для этого регистрируем переменную --progress:
@property --progress {
inherits: true;
initial-value: 0;
syntax: "<number>";
}И анимируем её:
.progress {
animation: progress 10s infinite alternate;
}
@keyframes progress {
to {
--progress: 100;
}
}Во время анимации автоматически меняется:
размер заполнителя,
цвет шкалы,
подпись в центре.
То есть все стили, завязанные на --progress, тоже пересчитываются на лету, когда нативная анимация меняет значение переменной.

Заключение
Ключевой приём во всей этой истории — множественные фоны с радиальным и коническим градиентами. Он прост, хорошо поддерживается и даёт большую гибкость.
Всё остальное — кастомизация, визуальные эффекты, условная логика, анимация — это надстройки, которые можно подключать по мере необходимости.
Если нужен надёжный продакшен‑компонент — используйте базовый приём. Если хочется поэкспериментировать и поддержка позволяет — используйте новые возможности. Они доступны в свежих версиях Chrome.
Надеюсь, вам будет приятнее делать прогрессбары в 2026 году!
Подписывайтесь на мой телеграм‑канал «CSS Боль», если хотите ещё больше интересного современного CSS и задавайте вопросы в комментариях.
