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!
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:
- sjekk at fargene våre har mye kontrast mellom dem,
- tillate tastaturbrukere å tappe til hver overlappende linje, og
- 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.