# Barra de progresso circular com CSS

> Crie barras de progresso circular impressionantes com CSS puro e Sass. Técnica diferenciada usando linear-gradient para 100 níveis de preenchimento radial!

URL: https://dpw.dev/css/barra-progresso-circular-css/  
Publicado em: 2020-05-25  
Categoria: css  
Tags: interface, sass  
Autor: Tárcio Zemel

Das diferentes manerias de fazer **barras de progresso circular**, a que você conhecerá agora, usando somente CSS, com certeza vai surpreender!

[Vídeo no YouTube](https://www.youtube.com/watch?v=JUufrBFeaAM)

Em [desenvolvimento web](/), quase sempre é possível chegar a resultados semelhantes usando técnicas diferentes. O mesmo vale para fazer um componente de barra de progresso circular -- ou _circular progress bar_, _radial progress bar_, _circular loading_, _barra de porcentagem radial_...

É possível fazer usando JavaScript, com imagens, imagens inline, SVGs, enfim, uma miríade de técnicas, das mais modernas às mais consagradas.

Mas essa daqui é diferente; a maneira como essas barras de progresso circular são feitas usando CSS puro (com uma mãozinha de Sass, para não cansar muito) é diferente de tudo o que você já viu.

## As bases da técnica para a barra de progresso circular

Além de diferente, a técnica é simples.

A ideia é usar `[linear-gradient()](https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient)` de maneira _ixpertinha_ para conseguir resultados visuais angulados, conforme cada porcentagem necessária em um componente radial desta natureza.

Na camada de conteúdo, pode ser somente um elemento vazio, como uma `div`, `i` ou `span`. Dando ênfase na metodologia BEM de nomenclatura, haverá um Modificador para cada grau de "loading" do círculo.

## O HTML necessário

Para o exemplo, optemos por usar `span` para o elemento:

```html
<span class="c-circular-progress"></span>
```

Então, conforme explicado, para conseguir a porcentagem que se queira, usa-se uma classe Modificadora com a porcentagem do loading que se quer:

```html
<span class="c-circular-progress c-circular-progress--4"></span>
```

Depois de feita a mágica com Sass, estarão disponíveis 100 classes Modificadoras para serem usadas, uma para cada grau de preenchimento da barra de progresso circular.

## Sass/CSS para a estilização

A base para o visual do componente é o seguinte:

```scss
$component-name: "c-circular-progress";

.#{$component-name} {
  border-radius: 50%;
  display: block;
  height: rem(250);
  margin: $global-module-size auto;
  position: relative;
  width: rem(250);

  &::before {
    align-items: center;
    background-color: var(--color-webfatorial-white);
    border-radius: 50%;
    display: inline-flex;
    font-size: 500%;
    height: 100%;
    justify-content: center;
    left: 0;
    position: absolute;
    top: 0;
    transform: scale(0.8);
    width: 100%;
  }
}
```

Perceba que a aparência do `::before` foi estabelecida, mas a propriedade `content` não está presente. Isso faz parte da técnica.

O conteúdo, o que será exibido textualmente, será o próprio valor da porcentagem atual, o que será alcançado dentro da geração automática das 100 classes com Sass.

Então, é hora de usar a diretiva `[@for](https://sass-lang.com/documentation/at-rules/control/for)` para ajudar a gerar essa centena de classes:

```scss
@for $i from 0 through 100 {
  $deg: 90deg + (3.6 * $i);

  &--#{$i} {
    $direction: if($i < 51, right, left);
    $color: if($i < 51, $color-background, $color-fill);

    background:
      linear-gradient(
        to #{$direction},
        #{$color} 50%,
        transparent 50%
      ),
      linear-gradient(
        #{$deg},
        $color-fill 50%,
        $color-background 50%
      );

    &::before {
      content: quote("#{$i}");
    }
  }
}
```

Vamos ao esclarecimento de alguns pontos (possivelmente) críticos.

### `$deg: 90deg + (3.6 * $i);`

Essa continha pode parecer muito complexa, mas não é tanto.

`90deg` refere-se ao valor-base adotado (uma divisão vertical no degradê para o início dos cálculos).

`3.6` pode parecer um valor aleatório, mas trata-se do equivalente a 1° no círculo que mostra a porcentagem/loading atual.

Que é multiplicado por `$i`, que é o valor atual do loop de Sass, com isso, gerando uma angulação apropriada, equivalente ao valor corrente usado no Modificador.

Por exemplo, quando o loop estiver em `10`, o cálculo será:

```js
90 + (3.6 * 10) // 126deg
```

Quando for `67`:

```js
90 + (3.6 * 67) // 331.2deg
```

E assim por diante, calculando os valores de ângulo/grau apropriados para cada uma das 100 classes geradas.

### `$direction: if($i < 51, right, left)`

[Desde Sass 3.3, é possível usar a função `if()`](http://thesassway.com/news/sass-3-3-released#a-nameif-classanchoraimproved-if-semantics) com sintaxe aprimorada, tratando-se de um ternário com estrutura i`f(condition, result-when-true, result-when-false)`.

A partir do valor `51`, é preciso alternar a direção e cor do degradê para o visual fique correto. Para evitar duplicação de códigos, esse ternários vêm a calhar.

Ah, e viu lá no `::before` o `content: quote("#{$i}");`? É o que foi comentado acima: cada Modificador dará o valor atual do número a ser exibido.

## Resultado final da barra de progresso circular

Viu como, além de diferente -- gerar barra de progresso circular usando background e linear-gradient() --, a técnica também é simples?

No final das contas, você vai conseguir gerar barra de porcentagem circular parecidas com:

<figure>

![Barra de progresso circular com CSS puro: exemplos do resultado final.](/images/blog/barra-progresso-circular-css/barra-progresso-circular-css-exemplo.webp)

<figcaption>

Exemplos do resultado final: visual da barra de progresso circular.

</figcaption>

</figure>

Só de alterar a classe Modificadora, tanto posição do loading, quanto número, são atualizados automaticamente.

Intervenção mínima na camada de conteúdo, alteração máxima no componente na camada de apresentação.

## Bônus: `data-*`

A técnica foi pensada com o uso de Modificadores BEM em mente. Entretanto, não é a única maneira de se alcançar o resultado final.

Se, por algum motivo, você não gosta muito da nomenclatura BEM (apesar de ela trazer muitas vantagens quando usada), também é possível usar atributos `data-*`.

Dentro do `@for` de Sass, quando da definição dos Modificadores, simplesmente altere o código para:

```scss
&--#{$i},
&[data-deg="#{$i}"] {
  // ...
}
```

Com isso, além de ser possível usar Modificadores, agora também será possível conseguir a barra circular de loading usando `data-deg` (você pode usar algum outro nome de sua preferência, claro) e passando o valor que se quer.

Na prática, agora estes 2 códigos são equivalentes, gerando a mesma barrinha circular:

```html
<span class="c-circular-progress c-circular-progress--33"></span>
<span class="c-circular-progress" data-deg="33"></span>
```

Como dizem, fica ao gosto do freguês. :)

## Conclusão

É possível fazer essa barrinha de loading circular usando JavaScript, com imagens, imagens inline, SVGs, enfim, uma miríade de técnicas, das mais modernas às mais consagradas.

Inclusive, abundam soluções JavaScript solo e com bibliotecas e frameworks para gráficos (para a surpresa de ninguém).

Mas essa solução é diferenciada: ela prima pela simplicidade de recursos e facilidade de uso. É uma solução _sem JavaScript_, que provê um _visual interessante e agradável_ para **barras de progresso circular**.

Para todos os passos de desenvolvimento da barra circular de progresso, assista ao vídeo no começo do artigo; para acessar o código completo, [acesse o código completo no repo do projeto](https://github.com/desenvolvweb/circular-progress-bar-pure-css).

E aí, gostou do resultado final? Tem usado 2MB de JavaScript para chegar a esse mesmo resultado? Conta pra gente aí nos comentários.

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
