Раньше, чтобы сделать круговой прогрессбар, мы страдали с 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 и задавайте вопросы в комментариях.
