Overlappende staafdiagrammen PlatoBlockchain Data Intelligence. Verticaal zoeken. Ai.

Overlappende staafdiagrammen

Zoals de naam al doet vermoeden, visualiseren overlappende grafieken twee verschillende gegevenssets in één diagram. Het idee is dat de overlappende balken ons in staat stellen om gegevens te vergelijken, zeg maar van jaar tot jaar. Ze zijn ook handig voor zaken als het bijhouden van de voortgang voor een doel waarbij de ene balk het doel vertegenwoordigt en de andere het huidige bedrag.

Maar ze zijn ook mooi!

Overlappende staafdiagrammen

Jouw geest is waarschijnlijk zoals de mijne en begint al uit te zoeken hoe je dat zou kunnen coderen. Hier is hoe ik het aanpakte.

De HTML

We beginnen met opmaak omdat, nou ja, dat is hoe we weten wat styling nodig heeft.

<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>

We zullen beschrijvingslijsten gebruiken (<dl>) omdat het een veel semantischere benadering is in vergelijking met standaard geordende en ongeordende lijsten. Een andere reden is dat we binnen elke balk een label opnemen. Normale lijsten hebben geen tag om een ​​titel of beschrijving toe te voegen, in tegenstelling tot definitielijsten. In eenvoudige bewoordingen is het gewoon logischer en ook leesbaarder.

De eerste beschrijvingslijst, .numbers, is de y-as. De .bars is waar de gegevens worden gevisualiseerd en ik heb een definitielijst gemaakt om ook de x-as te bouwen. Elk lijstitem bevat een .bar en het label als omschrijvingsterm (dt).

En hoe zit het met de gegevens? attribuut? De data-percentage wordt gebruikt om de hoogte van de staaf te specificeren, die uiteindelijk de waarde op de y-as vertegenwoordigt. We zouden het handmatig in CSS kunnen instellen voor elke balk, maar dat is repetitief en veel extra code die kan worden vervangen door een paar regels CSS.

De basisdiagramstijlen

We werken met veel tweedimensionale richtingen, dus flexbox wordt onze vriend om alles op een rij te krijgen. We kunnen de .chart element een flexibele container die de y-aslabels en de grafiek naast elkaar plaatst in de row richting.

.chart {
  display: flex;
}

We hoeven niet eens de richting op te geven, aangezien flexbox standaard is ingesteld op: row. Laten we dat doen en dan flexbox toevoegen aan de lijst met labels langs de y-as terwijl we toch bezig zijn, omdat we weten dat die in de column richting.

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

Geloof het of niet, we kunnen flexbox weer gebruiken voor de staven, want ook zij lopen in een row richting.

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

Ik heb dit zo ingesteld dat de .bars automatisch de ruimte innemen die over is door de y-axis .numbers.

Je hebt het waarschijnlijk opgemerkt in de HTML, maar "balk" is eigenlijk twee balken waar de ene de andere overlapt. Ik heb die in een generiek verpakt <div> die we kunnen gebruiken als nog een andere flexibele container die de definitieterm bevat (<dt>) die we gebruiken als label en de beschrijvingsdetails (<dd>) die beide staafwaarden bevat:

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

Elke balk zal dezelfde breedte hebben, vandaar: flex: 1. We positioneren het element relatief terwijl we toch bezig zijn, omdat we op het punt staan ​​elke balk absoluut te positioneren en we willen ervoor zorgen dat ze in hun containers blijven.

Elke staaf heeft een hoogtepercentage dat overeenkomt met de waarden langs de verticale y-as. Je herinnert je misschien ook dat we elke reep een gaven data-percentage attribuut - we gaan een beetje JavaScript toevoegen dat de hoogte van elke balk instelt met behulp van die waarden.

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

Dat is onze basiskaart!

We willen dit zover krijgen dat we de balken elkaar kunnen zien overlappen. Dat is de volgende!

Overlappende balken

De truc om de ene balk een andere te laten overlappen, is grappig omdat we dat vaak proberen voorkomen dingen visueel overlappen in CSS. Maar in dit geval willen we juist dat dat gebeurt.

De staven overlappen elkaar al; het is gewoon moeilijk te zeggen. Merk in de HTML op dat de tweede .bar in elke set heeft een extra .overlap klas. Laten we dat gebruiken om de balken te onderscheiden. Hierbij ben je geheel vrij om je eigen styling te kiezen. Ik voeg een beetje opvulling toe aan de .overlap staven zodat ze breder zijn dan de andere staven. Dan pas ik de stapelvolgorde aan met z-index zodat de .overlap bars zitten onder de andere bars.

Laten we een legende toevoegen

Legende. Wat een geweldig woord, niet? Boordevol allerlei betekenissen. In dit geval is het een meer dan leuke bijkomstigheid, omdat we visueel twee staven in de ruimten die normaal gesproken voor één staaf zijn gereserveerd, vastzetten. Een legenda biedt context waarin wordt uitgelegd wat elke balk vertegenwoordigt.

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

Met een <figure> voelt voor mij juist aan. Ze worden vaak gebruikt om afbeeldingen in te pakken, maar de spec zegt ze worden gebruikt "om illustraties, diagrammen, foto's, codelijsten, enz. te annoteren." en we werken met een diagram. We zouden waarschijnlijk een ongeordende lijst kunnen gebruiken om de items vast te houden, maar ik ging met een niet-semantische <div>. Als iemand een mening heeft over de beste manier om dit te markeren, ben ik een en al oor in de reacties!

Nogmaals, styling is helemaal aan jou:

Toegankelijkheidsoverwegingen

We hebben veel tijd besteed aan het nemen van beslissingen voor de opmaak en stijl van ons overlappende staafdiagram. Het is tot nu toe geweldig, maar we zijn zeker nog niet klaar, want er is meer dat we kunnen doen om er nog meer van te maken beschikbaar beleven. Niet iedereen is een ziende websurfer, dus er is wat extra werk te doen om de inhoud in die contexten over te brengen.

Concreet moeten we:

  1. controleer of onze kleuren voldoende contrast hebben,
  2. laat toetsenbordgebruikers toe om naar elke overlappende balk te taben, en
  3. zorg ervoor dat schermlezers de inhoud aankondigen.

Kleurcontrasten

We hebben voldoende contrast nodig tussen:

  • de overlappende staven
  • de balken en de achtergrond van de grafiek
  • de labeltekst en achtergrond

Ik heb van tevoren wat huiswerk gemaakt over de kleuren die ik heb gebruikt in de voorbeelden die we tot nu toe hebben bekeken, om ervoor te zorgen dat er genoeg contrast tussen de voorgrond en achtergrond om WCAG AA-conformiteit te bereiken.

Dit is wat ik gebruik:

  • Overlappende balken: (#25DEAA en #696969: 3.16:1 verhouding)
  • Staven en grafiekachtergrond (#696969 en #111: 3.43:1 verhouding)
  • Y-as label tekst en achtergrond (#fff en #333: 12.63: ​​1 verhouding)

Tabbladen tussen staven

Om dit te krijgen waar toetsenbordgebruikers elke individuele balk kunnen selecteren met de Tab sleutel, we kunnen naar de HTML reiken tabindex attribuut. We kunnen het volgende JavaScript gebruiken in de for-each-functie om deze eigenschap toe te voegen aan elke balk (beide). We zullen de tabbladindex instellen op: 0:

bar.setAttribute("tabindex", 0);

We kunnen ook wat CSS toevoegen om de omtrek te verbeteren wanneer de balk is geselecteerd terwijl we toch bezig zijn:

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

Inhoud aankondigen op schermlezers

Een ander belangrijk aspect van toegankelijkheid is ervoor te zorgen dat schermlezers de balken en hun percentages kunnen aankondigen.

We werken met twee verschillende grafieken in één: een grafiek die 'geschatte' waarden toont en een andere die 'werkelijke' waarden toont. Het zou geweldig zijn als de gebruiker wist welke balk werd aangekondigd, dus laten we ze labelen met de aria-label attribuut:

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

Merk op dat we de waarde van de balk ook rechtstreeks in de HTML hebben. Dat wordt aangekondigd, maar we willen het toch visueel verbergen. We zouden kunnen gebruiken transparent tekst daarvoor, maar een andere manier is om de klassiek .visually-hidden truc door de waarde in te wikkelen 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;
}

Terwijl we het hebben over het aankondigen van inhoud, kunnen we waarschijnlijk voorkomen dat de y-aslabels worden gelezen. Het is niet zo dat de gebruiker informatie mist, aangezien de werkelijke percentages voor elke balk al beschikbaar en aangekondigd zijn. We kunnen de aria-hidden attribuut daarvoor:

<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>

Ik denk ook dat het goed is voor schermlezers om de legende te negeren, omdat het een visueel hulpmiddel is:

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

De laatste demo

Het zit er op!

Daar gaan we, een grafiek met overlappende balken! Het is een leuke manier om gegevens te vergelijken en ik hoop dat je er een toepassing voor kunt vinden in een of ander project.

Zijn er andere manieren waarop we dit hadden kunnen aanpakken? Natuurlijk! Alles wat we hier hebben behandeld, leidt je alleen maar door mijn denkproces. Ik kan me voorstellen dat sommigen van jullie een andere benadering zouden hebben gekozen - als jij dat bent, deel het dan alsjeblieft! Het zou geweldig zijn om andere CSS-lay-outtechnieken en perspectieven te zien om de toegankelijkheid te verbeteren.

Tijdstempel:

Meer van CSS-trucs