Gráficos de barras sobrepostos PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Sobreposição de gráficos de barras

Como o nome sugere, os gráficos sobrepostos visualizam dois conjuntos diferentes de dados em um único diagrama. A ideia é que as barras sobrepostas nos permitam comparar dados, digamos, ano após ano. Eles também são úteis para monitorar o progresso de uma meta, onde uma barra representa a meta e a outra mostra o valor atual.

Mas eles são lindos também!

Sobreposição de gráficos de barras

Sua mente provavelmente é como a minha e já está começando a descobrir como você codificaria isso. Veja como eu resolvi isso.

O HTML

Vamos começar com a marcação porque, bem, é assim que sabemos o que precisa de estilo.

<div class="container">
  <div class="chart">
    <dl class="numbers">
      <dd><span>100%</span></dd>
      <!-- all the way to 0% -->
    </dl>
    <dl class="bars">
      <div>
          <dt>2018</dt>
          <dd>
            <div class="bar" data-percentage="50"></div>
            <div class="bar overlap" data-percentage="53"></div>
          </dd>
        </div>
      <div>
      <!-- more bars -->
    </dl>
  </div>
</div>

Estaremos usando listas de descrição (<dl>), pois é uma abordagem muito mais semântica em comparação com listas ordenadas e não ordenadas padrão. Outro motivo é que incluímos um rótulo em cada barra. As listas normais não possuem uma tag para adicionar um título ou descrição, ao contrário das listas de definição. Em termos simples, faz mais sentido e também é mais legível.

A primeira lista de descrição, .numbers, é o eixo y. O .bars é onde os dados são visualizados e fiz uma lista de definições para construir o eixo x também. Cada item da lista contém um .bar e o rótulo como termo descritivo (dt).

E o que há com os dados atributo? o data-percentage está sendo usado para especificar a altura da barra, que em última análise representa seu valor no eixo y. Poderíamos configurá-lo manualmente em CSS para cada barra, mas isso é repetitivo e tem muito código extra que pode ser substituído por algumas linhas de CSS.

Os estilos básicos de gráfico

Estamos trabalhando com muitas direções bidimensionais, então o flexbox será nosso amigo para alinhar tudo. Podemos fazer o .chart elemento um contêiner flexível que posiciona os rótulos do eixo y e o gráfico um ao lado do outro no row direção.

.chart {
  display: flex;
}

Nem precisamos especificar a direção, já que o padrão do flexbox é row. Vamos fazer isso e adicionar flexbox à lista de rótulos ao longo do eixo y enquanto estamos nisso, pois sabemos que eles serão executados no column direção.

.numbers {
  display: flex;
  flex-direction: column;
  list-style: none;
  margin: 0 15px 0 0;
  padding: 0;
}

Acredite ou não, podemos usar o flexbox novamente para as barras, já que elas também estão rodando em um row direção.

.bars {
  display: flex;
  flex: auto; /* fill up the rest of the `.chart` space */
  gap: 60px;
}

Eu configurei isso para que o .bars ocupar automaticamente qualquer espaço que sobrar do y-axis .numbers.

Você provavelmente notou isso no HTML, mas “barra” são na verdade duas barras onde uma se sobrepõe à outra. Eu embrulhei isso em um genérico <div> que podemos usar como mais um contêiner flexível que contém o termo de definição (<dt>) que estamos usando como rótulo e os detalhes da descrição (<dd>) que contém ambos os valores da barra:

.bars > div {
  align-items: center;
  display: flex;
  flex-direction: column;
  flex: 1;
  position: relative;
}

Cada barra terá a mesma largura, portanto flex: 1. Estamos posicionando relativamente o elemento enquanto fazemos isso porque estamos prestes a posicionar absolutamente cada barra e queremos ter certeza de que elas permaneçam em seus contêineres.

Cada barra tem uma altura percentual que corresponde aos valores ao longo do eixo y vertical. Você também deve se lembrar que demos a cada barra um data-percentage atributo - vamos adicionar um pouco de JavaScript que define a altura de cada barra usando esses valores.

var bars = document.querySelectorAll("dd .bar");
bars.forEach((bar) => {
  var height = bar.getAttribute("data-percentage");
  bar.style.height = height + "%";
});

Esse é o nosso gráfico básico!

Queremos chegar onde possamos ver as barras sobrepostas umas às outras. Isso é o próximo!

Barras sobrepostas

O truque para fazer com que uma barra se sobreponha a outra é engraçado porque muitas vezes tentamos evitar coisas se sobreponham visualmente em CSS. Mas, neste caso, realmente queremos que isso aconteça.

As barras já estão sobrepostas; é difícil dizer. Observe no HTML que o segundo .bar em cada conjunto tem um adicional .overlap aula. Vamos usar isso para diferenciar as barras. Você é totalmente livre para escolher seu próprio estilo para isso. Estou adicionando um pouco de preenchimento ao .overlap barras para que sejam mais largas que as outras barras. Então estou ajustando a ordem de empilhamento usando z-index para que o .overlap as barras ficam abaixo das outras barras.

Vamos adicionar uma legenda

Lenda. Uma palavra tão bonita, não é? Embalado com todos os tipos de significado. Neste caso, é um toque mais do que simpático porque, visualmente, estamos encravando dois compassos em espaços que normalmente são reservados para um compasso. Uma legenda fornece contexto que explica o que cada barra representa.

<figure class="legend">
  <div class="type1">Estimate</div>
  <div class="type2">Actual</div>
</figure>

Usando um <figure> parece correto para mim. Eles são frequentemente usados ​​para agrupar imagens, mas as especificações diz eles são usados ​​“para anotar ilustrações, diagramas, fotos, listagens de códigos, etc.” e estamos trabalhando com um diagrama. Provavelmente poderíamos usar uma lista não ordenada para armazenar os itens, mas optei por uma lista não semântica. <div>. Se alguém tiver uma opinião sobre a melhor forma de marcar isso, sou todo ouvidos nos comentários!

Mais uma vez, o estilo depende totalmente de você:

Considerações de acessibilidade

Gastamos muito esforço na tomada de decisões sobre a marcação e o estilo de nosso gráfico de barras sobreposto. Está ótimo até agora, mas definitivamente ainda não terminamos porque há mais que podemos fazer para tornar isso mais acessível experiência. Nem todo mundo é um internauta com visão, então há algum trabalho adicional a ser feito para transmitir o conteúdo nesses contextos.

Especificamente, precisamos:

  1. verifique se nossas cores têm bastante contraste entre elas,
  2. permitir que os usuários do teclado acessem cada barra sobreposta e
  3. certifique-se de que os leitores de tela anunciem o conteúdo.

Contrastes de cores

Precisamos de contraste suficiente entre:

  • as barras sobrepostas
  • as barras e o fundo do gráfico
  • o texto e o plano de fundo do rótulo

Fiz um pequeno trabalho de casa com antecedência sobre as cores que usei nos exemplos que vimos até agora, certificando-me de que há cores suficientes contraste entre o primeiro plano e o fundo para alcançar a conformidade com WCAG AA.

Aqui está o que estou usando:

  • Barras sobrepostas: (#25DEAA e #696969: proporção de 3.16:1)
  • Barras e plano de fundo do gráfico (#696969 e #111: proporção de 3.43:1)
  • Texto e plano de fundo do rótulo do eixo Y (#fff e #333: proporção de 12.63:1)

Tabulação entre barras

Para conseguir isso, os usuários do teclado podem selecionar cada barra individual com o Aba chave, podemos acessar o HTML tabindex atributo. Podemos usar o seguinte JavaScript dentro da função for-each para adicionar esta propriedade a cada barra (ambas). Definiremos o índice da guia como 0:

bar.setAttribute("tabindex", 0);

Também podemos adicionar algum CSS para melhorar o contorno quando a barra é selecionada:

.bar:focus {
  outline: 1.5px solid #f1f1f1;
}

Anunciando conteúdo em leitores de tela

Outro aspecto importante da acessibilidade é garantir que os leitores de tela possam anunciar as barras e suas porcentagens.

Estamos trabalhando com dois gráficos diferentes em um: um gráfico que mostra valores “Estimados” e outro que mostra valores “Reais”. Seria ótimo se o usuário soubesse qual barra está sendo anunciada, então vamos rotulá-la com o aria-label atributo:

<div class="bar" data-percentage="50" aria-label="Estimate">50%</div>

Observe que também temos o valor da barra diretamente no HTML. Isso será anunciado, mas ainda queremos ocultá-lo visualmente. Poderíamos usar transparent texto para isso, mas outra maneira é usar o clássico .visually-hidden truque envolvendo o valor em span:

<div class="bar" data-percentage="50" aria-label="Estimate">
  <span class="visually-hidden">50%</span>
</div>
.visually-hidden {
  clip: rect(0 0 0 0); 
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; 
  width: 1px;
}

Enquanto falamos sobre o anúncio de conteúdo, provavelmente podemos impedir que os rótulos do eixo y sejam lidos. Não é que falte informação ao usuário, pois os percentuais reais de cada barra já estão disponíveis e anunciados. Podemos usar o aria-hidden atributo para isso:

<dl class="numbers" aria-hidden="true">
  <dd><span>100%</span></dd>
  <dd><span>80%</span></dd>
  <dd><span>60%</span></dd>
  <dd><span>40%</span></dd>
  <dd><span>20%</span></dd>
  <dd><span>0%</span></dd>
</dl>

Também acho que os leitores de tela podem ignorar a legenda, pois é um auxílio visual:

<figure class="legend" aria-hidden="true">
  <div class="type1">Estimate</div>
  <div class="type2">Actual</div>
</figure>

A demonstração final

Isso é um embrulho!

Lá vamos nós, um gráfico com barras sobrepostas! É uma ótima maneira de comparar dados e espero que você encontre uma utilidade para ela em algum projeto.

Existem outras maneiras pelas quais poderíamos ter abordado isso? Claro! Tudo o que abordamos aqui é apenas orientar você em meu processo de pensamento. Imagino que alguns de vocês teriam adotado uma abordagem diferente – se for você, por favor, compartilhe! Seria ótimo ver outras técnicas de layout CSS e perspectivas sobre como acertar a acessibilidade.

Carimbo de hora:

Mais de Truques CSS