Você deve conhecer algumas maneiras de criar gráficos com CSS puro. Alguns deles são abordados aqui no CSS-Tricks , e muitos outros podem ser encontrados no CodePen , mas não vi muitos exemplos de “gráficos de área” (imagine um gráfico de linha com a área inferior preenchida), especialmente qualquer em HTML e CSS sozinho. Neste artigo, faremos exatamente isso, usando uma base HTML semântica e acessível.
Vamos começar com o HTML
Para simplificar as coisas, usaremos <ul>
tags como wrappers e <li>
elementos para itens de dados individuais. Você pode usar qualquer outra tag HTML em seu projeto, dependendo de suas necessidades.
<ul class="area-chart">
<li> 40% </li>
<li> 80% </li>
<li> 60% </li>
<li> 100% </li>
<li> 30% </li>
</li>
CSS não pode recuperar o texto HTML interno, é por isso que usaremos propriedades customizadas CSS para passar dados ao nosso CSS. Cada item de dados terá um --start
e --end
propriedades personalizadas.
<ul class="area-chart">
<li style="--start: 0.1; --end: 0.4;"> 40% </li>
<li style="--start: 0.4; --end: 0.8;"> 80% </li>
<li style="--start: 0.8; --end: 0.6;"> 60% </li>
<li style="--start: 0.6; --end: 1.0;"> 100% </li>
<li style="--start: 1.0; --end: 0.3;"> 30% </li>
</li>
Aqui está o que precisamos considerar …
Existem vários princípios de design que devemos considerar antes de passar para o estilo:
- Dados Unidades: Nós estaremos usando dados da unidade-less na nossa HTML (ou seja, sem
px
,em
,rem
,%
ou qualquer outra unidade). As propriedades personalizadas--start
e--end
serão números entre 0 e 1. - Largura das colunas: não definiremos um valor fixo
width
para cada<li>
elemento. Também não%
usaremos, pois não sabemos quantos itens existem. A largura de cada coluna será baseada na largura do wrapper principal, dividida pelo número total de itens de dados. No nosso caso, essa é a largura do<ul>
elemento dividido pelo número de<li>
elementos. - Acessibilidade: os valores dentro de cada um
<li>
são opcionais e apenas as propriedades personalizadas--start
e--end
são obrigatórias. Ainda assim, é melhor incluir algum tipo de texto ou valor para leitores de tela e outras tecnologias de assistência para descrever o conteúdo.
Agora, vamos começar a estilizar!
Vamos começar com o estilo geral do layout primeiro. O elemento do wrapper do gráfico é um flex container, exibindo itens em uma linha, estendendo cada elemento filho para que toda a área seja preenchida.
.area-chart {
/* Reset */
margin: 0;
padding: 0;
border: 0;
/* Dimensions */
width: 100%;
max-width: var(--chart-width, 100%);
height: var(--chart-height, 300px);
/* Layout */
display: flex;
justify-content: stretch;
align-items: stretch;
flex-direction: row;
}
Se o wrapper do gráfico de área for uma lista, devemos remover o estilo de lista para nos dar mais flexibilidade de estilo.
ul.area-chart,
ol.area-chart {
list-style: none;
}
Este código define o estilo de todas as colunas do gráfico inteiro. Com gráficos de barras é simples: usamos background-color
e height
para cada coluna. Com de char área ts vamos usar a clip-path
propriedade para definir a região que deve ser mostrado.
Primeiro, configuramos cada coluna:
.area-chart > * {
/* Even size items */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
/* Color */
background: var(--color, rgba(240, 50, 50, .75));
}
Para criar um retângulo cobrindo toda a área, vamos pegar a clip-path
propriedade e usar sua polygon()
função contendo as coordenadas da área. Isso basicamente não faz nada no momento porque o polígono cobre tudo:
.area-chart > * {
clip-path: polygon(
0% 0%, /* top left */
100% 0%, /* top right */
100% 100%, /* bottom right */
0% 100% /* bottom left */
);
}
Agora para a melhor parte!
Para mostrar apenas parte da coluna, nós a recortamos para criar aquele efeito de gráfico de área. Para mostrar apenas a área que queremos, usamos as propriedades personalizadas --start
e --end
dentro do clip-path
polígono:
.area-chart > * {
clip-path: polygon(
0% calc(100% * (1 - var(--start))),
100% calc(100% * (1 - var(--end))),
100% 100%,
0% 100%
);
}
Sério, esse único pedaço de CSS faz todo o trabalho. Aqui está o que temos:
Trabalhar com vários conjuntos de dados
Agora que sabemos o básico, vamos criar um gráfico de área com vários conjuntos de dados. Os gráficos de área geralmente medem mais de um conjunto de dados e o efeito é uma comparação em camadas dos dados.
Esse tipo de gráfico requer vários elementos filho, portanto, vamos substituir nossa <ul>
abordagem por um <table>
.
<table class="area-chart">
<tbody>
<tr>
<td> 40% </td>
<td> 80% </td>
</tr>
<tr>
<td> 60% </td>
<td> 100% </td>
</tr>
</tbody>
</table>
As tabelas são acessíveis e amigáveis aos motores de busca. E se a folha de estilo não carregar por algum motivo, todos os dados ainda estarão visíveis na marcação.
Novamente, usaremos as propriedades personalizadas --start
e --end
com números entre 0 e 1.
<table class="area-chart">
<tbody>
<tr>
<td style="--start: 0; --end: 0.4;"> 40% </td>
<td style="--start: 0; --end: 0.8;"> 80% </td>
</tr>
<tr>
<td style="--start: 0.4; --end: 0.6;"> 60% </td>
<td style="--start: 0.8; --end: 1.0;"> 100% </td>
</tr>
</tbody>
</table>
Portanto, primeiro definiremos o layout geral do elemento de embalagem, nossa tabela, que demos uma .area-chart
classe:
.area-chart {
/* Reset */
margin: 0;
padding: 0;
border: 0;
/* Dimensions */
width: 100%;
max-width: var(--chart-width, 600px);
height: var(--chart-height, 300px);
}
A seguir, faremos do <tbody>
elemento um flex container, exibindo os <tr>
itens em uma linha e dimensionados uniformemente:
.area-chart tbody {
width: 100%;
height: var(--chart-height, 300px);
/* Layout */
display: flex;
justify-content: stretch;
align-items: stretch;
flex-direction: row;
}
.area-chart tr {
/* Even size items */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
Agora precisamos fazer com que os <td>
elementos cubram uns aos outros, um elemento em cima do outro, para obtermos esse efeito em camadas. Cada um <td>
cobre toda a área do <tr>
elemento que o contém.
.area-chart tr {
position: relative;
}
.area-chart td {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
Vamos colocar os poderes mágicos do clip-path: polygon()
em uso! Nós só está exibindo a área entre os --start
e --end
propriedades personalizadas que, novamente, são valores entre 0 e 1:
.area-chart td {
clip-path: polygon(
0% calc(100% * (1 - var(--start))),
100% calc(100% * (1 - var(--end))),
100% 100%,
0% 100%
);
}
Agora vamos adicionar cor a cada um:
.area-chart td {
background: var(--color);
}
.area-chart td:nth-of-type(1) {
--color: rgba(240, 50, 50, 0.75);
}
.area-chart td:nth-of-type(2) {
--color: rgba(255, 180, 50, 0.75);
}
.area-chart td:nth-of-type(3) {
--color: rgba(255, 220, 90, 0.75);
}
É importante usar cores com opacidade para obter um efeito mais agradável, e é por isso que usamos rgba()
valores. Você pode usar hsla()
aqui, se for assim.
E assim:
Empacotando
Não importa quantos elementos HTML adicionamos ao nosso gráfico, o layout baseado em flex garante que todos os itens tenham o mesmo tamanho. Dessa forma, precisamos apenas definir a largura do elemento do gráfico de envolvimento e os itens serão ajustados de acordo para um layout responsivo.