Круговые диаграммы — это распространенные компоненты, позволяющие отображать части целого. Их можно использовать для самых разных целей.
О создании таких компонентов вы найдете множество статей. Но диаграммы в них обычно делаются либо на основе SVG, либо с применением большого числа HTML-элементов.
В этой статье я расскажу, как создать круговую диаграмму, используя CSS и всего один HTML-элемент.
Ниже, в CodePen, можно посмотреть, что мы будем создавать:
See the Pen CSS only pie chart by Temani Afif (@t_afif) on CodePen.
Как видите, у нас есть статичная и анимированная круговая диаграмма, в которых также могут быть закругленные концы. Все это сделано с помощью одного элемента <div>
.
В дополнение к этому мы можем легко настроить различные значения с помощью CSS-переменных, благодаря чему нам не придется беспокоиться об изменении CSS-кода.
Я знаю, что на первый взгляд код может показаться немного сложным, но после прочтения пояснений вы сможете уверенно создавать свои собственные круговые диаграммы.
Структура HTML для круговой диаграммы
Как я упоминал выше, у нас есть один <div>
, куда мы добавляем процентное значение (прогресс круговой диаграммы) в качестве основного содержимого:
<div class="pie" style="--p:60;--b:10px;--c:purple;">60%</div>
Мы также добавляем CSS-переменные в качестве встроенных стилей.
--p
: Эта переменная должна содержать процентное значение в виде числа (без знака %). Значение должно быть таким же, как в содержимом <div>.--b
: Эта переменная определяет толщину границы.--c
: Эта переменная определяет основной цвет.
Для целей этой статьи, чтобы код был покороче, я использую однобуквенные переменные. В продакшен-среде, конечно, нужно использовать более осмысленные имена. Например, --percentage
, --border-thickness
и --main-color
.
CSS для круговой диаграммы
Начнем со стилизации содержимого. Здесь все просто, код у нас будет следующий:
.pie { --w: 150px; width: var(--w); aspect-ratio: 1; display: inline-grid; place-content: center; margin: 5px; font-size: 25px; font-weight: bold; font-family: sans-serif; }
(Прим. перев.: «pie» в коде — от англ. «Pie Chart» — «круговая диаграмма»).
Я определяю наш элемент как inline-grid
, чтобы легко разместить содержимое в середине при помощи place-content: center
. Чтобы наш элемент всегда оставался квадратным, мы используем aspect-ratio: 1
. Также можно использовать height: var(--w)
, но всегда полезно изучать и применять новые CSS-свойства.
Возможно, вам любопытно, почему для определения ширины я использую переменную, а не просто прописываю width: 150px
. В будущем мне понадобится это значение, поэтому я определяю его при помощи переменной.
Весь остальной CSS-код довольно простой и касается стилизации текста. Можете его изменить по своему вкусу.
Переходим к более интересной части — основной форме нашего компонента. Для этого мы используем псевдоэлемент со следующими стилями:
.pie:before{ content: ""; position: absolute; border-radius: 50%; inset: 0; background: conic-gradient(var(--c) calc(var(--p)*1%),#0000 0); }
Псевдоэлемент, имеющий position: absolute
, покрывает всю площадь благодаря inset: 0
. Да, еще одно новое CSS-свойство. Это сокращенный вариант для top
, right
, bottom
и left
(почитать подробнее можно на MDN Web Docs).
Затем мы превращаем наш псевдоэлемент в круг (border-radius: 50%
) и применяем conic-gradient()
. Обратите внимание на использование CSS-переменных, которые мы определили в качестве встроенных стилей (--c
для цвета и --p
для процентного значения).
Пока что мы получаем вот такой результат:
Мы подбираемся к желаемой цели! conic-gradient()
дает нам двуцветный градиент. Основной цвет — от 0% до p%, а остальная часть имеет прозрачный цвет (со значением #0000).
Чтобы оставить только границу, мы прячем середину круга при помощи mask
. На этот раз мы используем radial-gradient()
:
radial-gradient(farthest-side,red calc(99% - var(--b)),blue calc(100% - var(--b)))
В качестве фона это дает нам следующий результат:
Обратите внимание на использование переменной --b
, которая определяет толщину границы (на рисунке показано синим цветом).
Теперь представьте, что синяя часть остается, а красная становится невидимой. Это мы и получаем, применяя тот же градиент со свойством mask
:
И вот, мы построили нашу круговую диаграмму на одном элементе и нескольких строках CSS-кода.
.pie { --w:150px; width: var(--w); aspect-ratio: 1; position: relative; display: inline-grid; place-content: center; margin: 5px; font-size: 25px; font-weight: bold; font-family: sans-serif; } .pie:before { content: ""; position: absolute; border-radius: 50%; inset: 0; background: conic-gradient(var(--c) calc(var(--p)*1%),#0000 0); -webkit-mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b))); mask:radial-gradient(farthest-side,#0000 calc(99% - var(--b)),#000 calc(100% - var(--b))); }
И HTML:
<div class="pie" style="--p:60;--b:10px;--c:purple;">60%</div>
Как добавить скругление краев
Я добавлю дополнительный градиентный слой для первого (верхнего) конца и псевдоэлемент для второго. Вот иллюстрация этого приема:
Код для скругления верхнего конца:
.pie:before { background: radial-gradient(farthest-side,var(--c) 98%,#0000) top/var(--b) var(--b) no-repeat, conic-gradient(var(--c) calc(var(--p)*1%),#0000 0); }
Помимо conic-gradient()
, сверху мы добавляем radial-gradient()
. Размер равен толщине границы (определяется при помощи --b
).
Код для скругления второго конца:
.pie:after { content: ""; position: absolute; border-radius: 50%; inset: calc(50% - var(--b)/2); background: var(--c); transform: rotate(calc(var(--p)*3.6deg)) translate(calc(50% - var(--w)/2)); }
Свойство inset устанавливает размер псевдоэлемента равным --b
. Помните, что это сокращенный вариант записи для top
, right
, bottom
и left
.
Если у нас
left = right = 50% - b/2
это значит, что с каждой стороны мы сдвигаемся к центру, за минусом отступа в b/2
. Таким образом у нас получается ширина, равная 2*b/2 = b
. Та же логика применяется к высоте.
Теперь нам нужно правильно разместить наш элемент. Для этого мы используем свойство transform
. Изначально элемент расположен по центру, так что нам нужно его повернуть. Имея процентное значение, мы применяем тройное правило, чтобы получить угол:
angle = percentage*360deg/100
Затем мы выполняем смещение. Здесь нам понадобится ширина, потому что смещение мы делаем на половину ширины (w/2
).
Ладно, ладно, возможно, вы уже потерялись во всех этих формулах. Представленная ниже иллюстрация поможет вам понять логику, стоящую за свойством transform
.
После этого мы раскрашиваем псевдоэлемент основным цветом — и все готово. Мы получили круговую диаграмму со скругленными концами.
Как анимировать круговую диаграмму
Статическая диаграмма это, конечно, хорошо, но анимированная лучше! Для этого мы будем анимировать процентное значение --p
от 0 до определенного значения. По умолчанию CSS-переменные не анимируются, но благодаря новой фиче @property
это стало возможным.
Регистрируем переменную:
@property --p{ syntax: '<number>'; inherits: true; initial-value: 0; }
Создаем keyframes
:
@keyframes p { from {--p:0} }
Обратите внимание: нам нужно указать только значение from
. По умолчанию браузер сделает значение to
равным определенному нами значению (<div class="pie" style="--p:60;">60%</div>
).
И, наконец, мы вызываем анимацию. При желании можете определить продолжительность и задержку.
animation: p 1s .5s both;
К сожалению, эта техника не имеет широкой поддержки. Вы можете протестировать ее в браузерах на основе Chromium (Chrome и Edge), но в Firefox и Safari фокус не сработает. Чтобы подробнее узнать о поддержке, откройте Can I Use.
Прежде чем завершить статью, покажу еще раз код целиком, а также демо финального продукта. Как видите, я использовал два класса для управления скругленными концами и анимацией, так что мы можем с легкостью добавлять и убирать их.
See the Pen CSS only pie chart by Temani Afif (@t_afif) on CodePen.
Перевод статьи «How to Create a Pie Chart Using Only CSS».
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]
Заняно, спасибо за статью!