Overlappende stolpediagram PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Overlappende søylediagrammer

Som navnet antyder, visualiserer overlappende diagrammer to forskjellige sett med data i et enkelt diagram. Tanken er at de overlappende søylene lar oss sammenligne data, for eksempel år-over-år. De er også nyttige for ting som å spore fremgang for et mål der en stolpe representerer målet og den andre viser gjeldende beløp.

Men de er også vakre!

Overlappende søylediagrammer

Sinnet ditt er sannsynligvis likt mitt og begynner allerede å finne ut hvordan du vil gå av og kode det. Her er hvordan jeg taklet det.

HTML

Vi skal begynne med markering fordi, vel, det er slik vi vet hva som trenger styling.

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

Vi vil bruke beskrivelseslister (<dl>) siden det er en mye mer semantisk tilnærming sammenlignet med standardordnede og uordnede lister. En annen grunn er at vi inkluderer en etikett i hver bar. Vanlige lister har ikke en kode i seg for å legge til en tittel eller beskrivelse i motsetning til definisjonslister. Enkelt sagt gir det bare mer mening og er også mer lesbart.

Den første beskrivelseslisten, .numbers, er y-aksen. De .bars er der dataene blir visualisert og jeg har laget en definisjonsliste for å bygge x-aksen også. Hvert listeelement inneholder en .bar og etiketten som en beskrivelsesterm (dt).

Og hva skjer med dataene attributt? De data-percentage brukes til å spesifisere høyden på stolpen, som til slutt representerer verdien på y-aksen. Vi kan manuelt sette det i CSS for hver linje, men det er repeterende og mye ekstra kode som kan erstattes med noen få linjer med CSS.

De grunnleggende diagramstilene

Vi jobber med mange todimensjonale retninger, så flexbox kommer til å være vår venn for å få alt på plass. Vi kan lage .chart element en fleksibel beholder som plasserer y-akseetikettene og diagrammet ved siden av hverandre i row retning.

.chart {
  display: flex;
}

Vi trenger ikke engang å spesifisere retningen siden flexbox er standard row. La oss gjøre det og så legge til flexbox i listen over etiketter langs y-aksen mens vi er i gang siden vi vet at de vil kjøre i column retning.

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

Tro det eller ei, vi kan bruke flexbox igjen til stengene siden de også kjører i en row retning.

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

Jeg har satt opp dette slik at .bars tar automatisk opp den plassen som er til overs y-axis .numbers.

Du har sikkert lagt merke til det i HTML-en, men "bar" er faktisk to stolper der den ene overlapper den andre. Jeg pakket dem inn i en generisk <div> at vi kan bruke som enda en fleksibel beholder som inneholder definisjonsbegrepet (<dt>) vi bruker som en etikett og beskrivelsesdetaljene (<dd>) som inneholder begge søyleverdiene:

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

Hver stolpe kommer derfor til å ha samme bredde flex: 1. Vi posisjonerer elementet relativt mens vi er i gang, fordi vi er i ferd med å absolutt plassere hver bar og vi vil sørge for at de forblir i beholderne sine.

Hver stolpe har en prosenthøyde som tilsvarer verdiene langs den vertikale y-aksen. Du husker kanskje også at vi ga hver bar en data-percentage attributt — vi skal strø inn litt JavaScript som angir høyden på hver stolpe ved hjelp av disse verdiene.

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

Det er vårt grunnleggende diagram!

Vi ønsker å få dette til der vi kan se stolpene overlappe hverandre. Det er neste!

Overlappende stolper

Trikset for å få en bar til å overlappe en annen er morsomt fordi vi ofte prøver det forebygge ting fra å overlappe visuelt i CSS. Men i dette tilfellet ønsker vi faktisk at det skal skje.

Stolpene overlapper allerede hverandre; det er bare vanskelig å si. Legg merke til i HTML-en at den andre .bar i hvert sett har en ekstra .overlap klasse. La oss bruke det til å skille stolpene. Du står helt fritt til å velge din egen styling for dette. Jeg legger til litt polstring til .overlap stengene slik at de er bredere enn de andre stengene. Deretter justerer jeg stablingsrekkefølgen ved hjelp av z-index slik at .overlap barer sitter under de andre stolpene.

La oss legge til en legende

Legende. Så flott ord, ikke sant? Fullpakket med all slags mening. I dette tilfellet er det mer enn en fin detalj fordi vi visuelt setter to barer i rom som vanligvis er reservert for én bar. En legende gir kontekst som forklarer hva hver stolpe representerer.

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

Ved hjelp av en <figure> føles riktig for meg. De brukes ofte til å pakke inn bilder, men spesifikasjonen sier de brukes "til å kommentere illustrasjoner, diagrammer, bilder, kodelister osv." og vi jobber med et diagram. Vi kunne nok brukt en uordnet liste for å holde varene, men jeg gikk med en usemantisk <div>. Hvis noen har en mening om den beste måten å markere dette på, er jeg med på kommentarene!

Nok en gang er styling helt opp til deg:

Tilgjengelighetshensyn

Vi har brukt mye av innsatsen på å ta avgjørelser for markering og styling av vårt overlappende søylediagram. Det er flott så langt, men vi er definitivt ikke ferdige fordi det er mer vi kan gjøre for å gjøre dette til en mer tilgjengelig erfaring. Ikke alle er seende nettsurfere, så det er litt ekstra arbeid å gjøre for å formidle innholdet i disse sammenhengene.

Konkret må vi:

  1. sjekk at fargene våre har mye kontrast mellom dem,
  2. tillate tastaturbrukere å tappe til hver overlappende linje, og
  3. sørg for at skjermlesere annonserer innholdet.

Fargekontraster

Vi trenger nok kontrast mellom:

  • de overlappende stolpene
  • søylene og diagrambakgrunnen
  • etikettteksten og bakgrunnen

Jeg gjorde litt lekser på forhånd om fargene jeg brukte i eksemplene vi har sett på så langt, og passet på at det er nok kontrast mellom forgrunn og bakgrunn for å oppnå WCAG AA-samsvar.

Her er hva jeg bruker:

  • Overlappende stolper: (#25DEAA og #696969: 3.16:1 forhold)
  • Søyler og diagrambakgrunn (#696969 og #111: 3.43:1 forhold)
  • Y-akse etiketttekst og bakgrunn (#fff og #333: 12.63:1 forhold)

Tabling mellom stolper

For å få dette der tastaturbrukere kan velge hver enkelt linje med Tab nøkkel, kan vi strekke oss etter HTML tabindex Egenskap. Vi kan bruke følgende JavaScript i for-hver-funksjonen for å legge til denne egenskapen til hver bar (begge). Vi vil sette faneindeksen til 0:

bar.setAttribute("tabindex", 0);

Vi kan også legge til litt CSS for å forbedre omrisset når linjen er valgt mens vi er i gang:

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

Kunngjøring av innhold på skjermlesere

Et annet viktig aspekt ved tilgjengelighet er å sørge for at skjermlesere kan kunngjøre søylene og deres prosentandeler.

Vi jobber med to forskjellige diagrammer i ett: et diagram som viser "estimerte" verdier og et annet som viser "faktiske" verdier. Det ville vært flott om brukeren visste hvilken bar som ble annonsert, så la oss merke dem med aria-label Egenskap:

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

Legg merke til at vi har barens verdi direkte i HTML-en også. Det vil bli annonsert, men vi ønsker fortsatt å skjule det visuelt. Vi kunne bruke transparent tekst for det, men en annen måte er å bruke Classic .visually-hidden trick ved å pakke verdien inn 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;
}

Mens vi snakker om å annonsere innhold, kan vi sannsynligvis forhindre at etikettene på y-aksen blir lest. Det er ikke slik at brukeren mangler informasjon, da de faktiske prosentene for hver søyle allerede er tilgjengelige og annonsert. Vi kan bruke aria-hidden attributt for det:

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

Jeg synes også det er OK for skjermlesere å ignorere legenden siden det er et visuelt hjelpemiddel:

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

Den siste demoen

Det er en wrap!

Der går vi, et diagram med overlappende stolper! Det er en fin måte å sammenligne data på, og jeg håper du kan bruke det på et eller annet prosjekt.

Er det andre måter vi kunne ha nærmet oss dette på? Selvfølgelig! Alt vi dekket her er bare å lede deg gjennom tankeprosessen min. Jeg antar at noen av dere ville ha tatt en annen tilnærming – hvis det er dere, del gjerne! Det ville vært flott å se andre CSS-layoutteknikker og perspektiver på hvordan man kan finne tilgjengeligheten.

Tidstempel:

Mer fra CSS triks