Круговая диаграмма на чистом CSS

1
3315
views
verstka logo

Хочешь знать больше про веб?

Подпишись на наш телеграм-канал TechRocks WEB-разработка?

×
Image by Gerd Altmann from Pixabay

Круговые диаграммы — это распространенные компоненты, позволяющие отображать части целого. Их можно использовать для самых разных целей.

О создании таких компонентов вы найдете множество статей. Но диаграммы в них обычно делаются либо на основе 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 к псевдоэлементу

Мы подбираемся к желаемой цели! conic-gradient() дает нам двуцветный градиент. Основной цвет — от 0% до p%, а остальная часть имеет прозрачный цвет (со значением #0000).

Чтобы оставить только границу, мы прячем середину круга при помощи mask. На этот раз мы используем radial-gradient():

radial-gradient(farthest-side,red calc(99% - var(--b)),blue calc(100% - var(--b)))

В качестве фона это дает нам следующий результат:

Применение radial-gradient()

Обратите внимание на использование переменной --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».

1 КОММЕНТАРИЙ

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here