Nakładające się wykresy słupkowe PlatoBlockchain Data Intelligence. Wyszukiwanie pionowe. AI.

Nakładające się wykresy słupkowe

Jak sama nazwa wskazuje, nakładające się wykresy wizualizują dwa różne zestawy danych na jednym diagramie. Chodzi o to, że nakładające się słupki pozwalają nam porównywać dane, powiedzmy, rok do roku. Są również przydatne do takich rzeczy, jak śledzenie postępu celu, gdzie jeden pasek reprezentuje cel, a drugi pokazuje aktualną kwotę.

Ale też są piękne!

Nakładające się wykresy słupkowe

Twój umysł jest prawdopodobnie taki jak mój i już zaczyna zastanawiać się, jak to zrobić i zakodować to. Oto jak sobie z tym poradziłem.

HTML

Zaczniemy od znaczników, ponieważ, no cóż, dzięki temu wiemy, co wymaga stylizacji.

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

Będziemy używać list opisowych (<dl>), ponieważ jest to podejście znacznie bardziej semantyczne w porównaniu ze standardowymi listami uporządkowanymi i nieuporządkowanymi. Innym powodem jest to, że dołączamy etykietę do każdego słupka. W przeciwieństwie do list definicji, listy normalne nie zawierają w sobie znacznika umożliwiającego dodanie tytułu lub opisu. Mówiąc prościej, jest to po prostu bardziej sensowne i bardziej czytelne.

Pierwsza lista opisów, .numbers, to oś y. The .bars to miejsce, w którym wizualizowane są dane, a także stworzyłem listę definicji, aby zbudować oś X. Każdy element listy zawiera .bar oraz etykieta jako termin opisowy (dt).

A co się dzieje z danymi? atrybut? data-percentage służy do określenia wysokości słupka, która ostatecznie reprezentuje jego wartość na osi y. Moglibyśmy ręcznie ustawić go w CSS dla każdego paska, ale jest to powtarzalne i dużo dodatkowego kodu, który można zastąpić kilkoma wierszami CSS.

Podstawowe style wykresów

Pracujemy z wieloma dwuwymiarowymi kierunkami, więc flexbox będzie naszym przyjacielem w uporządkowaniu wszystkiego. Możemy zrobić .chart element elastycznego pojemnika, który umieszcza etykiety osi Y i wykres obok siebie w row kierunek.

.chart {
  display: flex;
}

Nie musimy nawet określać kierunku, ponieważ flexbox domyślnie to row. Zróbmy to, a następnie dodajmy flexbox do listy etykiet wzdłuż osi y, skoro już przy tym jesteśmy, ponieważ wiemy, że będą one działać w column kierunek.

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

Wierzcie lub nie, możemy ponownie użyć flexboxa do barów, ponieważ one też działają w a row kierunek.

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

Ustawiłem to tak, że .bars automatycznie zabiera miejsce, które pozostało po y-axis .numbers.

Prawdopodobnie zauważyłeś to w kodzie HTML, ale „pasek” to w rzeczywistości dwa paski, z których jeden nakłada się na drugi. Zapakowałem je w rodzajowy <div> że możemy użyć jako kolejnego elastycznego kontenera, który zawiera termin definicji (<dt>) używamy jako etykiety i szczegółów opisu (<dd>), który przechowuje obie wartości słupków:

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

Każdy pasek będzie miał taką samą szerokość, stąd flex: 1. Stosunkowo pozycjonujemy element, ponieważ jesteśmy przy nim, ponieważ zamierzamy bezwzględnie pozycjonować każdy pasek i chcemy mieć pewność, że pozostaną w swoich pojemnikach.

Każdy słupek ma procentową wysokość odpowiadającą wartościom na pionowej osi y. Możesz też pamiętać, że każdemu batonowi daliśmy data-percentage atrybut — dodamy mały JavaScript, który ustawia wysokość każdego słupka przy użyciu tych wartości.

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

To nasz podstawowy wykres!

Chcemy doprowadzić to do miejsca, w którym widzimy zachodzące na siebie paski. To następny!

Nakładające się paski

Sztuczka polegająca na nakładaniu się jednego paska na drugi jest zabawna, ponieważ często próbujemy zapobiec rzeczy z nakładania się wizualnie w CSS. Ale w tym przypadku tak naprawdę chcemy, aby tak się stało.

Słupki już się nakładają; po prostu trudno powiedzieć. Zauważ w HTML, że drugi .bar w każdym zestawie posiada dodatkowe .overlap klasa. Użyjmy tego do rozróżnienia słupków. W tym celu możesz całkowicie wybrać własną stylizację. Dodaję trochę wyściółki do .overlap pręty, aby były szersze niż inne pręty. Następnie poprawiam kolejność układania za pomocą z-index tak, że .overlap bary siedzą pod innymi barami.

Dodajmy legendę

Legenda. Świetne słowo, prawda? Pełen wszelkiego rodzaju znaczeń. W tym przypadku jest to więcej niż miły akcent, ponieważ wizualnie blokujemy dwa takty w miejscach, które zwykle są zarezerwowane dla jednego taktu. Legenda zapewnia kontekst, który wyjaśnia, co reprezentuje każdy słupek.

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

Korzystanie <figure> czuje się dobrze do mnie. Są często używane do zawijania obrazów, ale specyfikacja mówią są używane „do opisywania ilustracji, diagramów, zdjęć, wykazów kodów itp.” i pracujemy z diagramem. Prawdopodobnie moglibyśmy użyć nieuporządkowanej listy do przechowywania przedmiotów, ale poszedłem z niesemantycznym <div>. Jeśli ktoś ma opinię na temat najlepszego sposobu, aby to zaznaczyć, wszyscy słyszę w komentarzach!

Po raz kolejny stylizacja zależy wyłącznie od Ciebie:

Uwagi dotyczące dostępności

Wiele wysiłku poświęciliśmy na podejmowanie decyzji dotyczących znaczników i stylizacji naszego nakładającego się wykresu słupkowego. Jak dotąd jest świetnie, ale na pewno jeszcze nie skończyliśmy, ponieważ możemy zrobić więcej, aby to było bardziej dostępny doświadczenie. Nie każdy jest widzącym internautą, więc jest trochę dodatkowej pracy do wykonania, aby przekazać treść w tych kontekstach.

W szczególności musimy:

  1. sprawdź, czy nasze kolory mają między sobą duży kontrast,
  2. zezwól użytkownikom klawiatury na tabulatory na każdym nakładającym się pasku i
  3. upewnij się, że czytniki ekranu ogłaszają treść.

Kontrasty kolorystyczne

Potrzebujemy wystarczającego kontrastu między:

  • nakładające się pręty
  • słupki i tło wykresu
  • tekst etykiety i tło

Zrobiłem wcześniej małą pracę domową z kolorów, których użyłem w przykładach, które do tej pory oglądaliśmy, upewniając się, że jest ich wystarczająco kontrast między pierwszym planem a tłem aby osiągnąć zgodność z WCAG AA.

Oto czego używam:

  • Zachodzące na siebie paski: (#25DEAA i #696969: stosunek 3.16:1)
  • Słupki i tło wykresu (#696969 i #111: stosunek 3.43:1)
  • Tekst i tło etykiety na osi Y (#fff i #333: stosunek 12.63:1)

Tabulatory między taktami

Aby to uzyskać, użytkownicy klawiatury mogą wybrać każdy indywidualny pasek za pomocą zakładka klucz, możemy sięgnąć po HTML tabindex atrybut. Możemy użyć następującego JavaScript wewnątrz funkcji for-each, aby dodać tę właściwość do każdego paska (obydwóch). Ustawimy indeks zakładek na 0:

bar.setAttribute("tabindex", 0);

Możemy również dodać trochę kodu CSS, aby poprawić zarys, gdy pasek jest zaznaczony, gdy jesteśmy na nim:

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

Ogłaszanie treści na czytnikach ekranu

Innym ważnym aspektem dostępności jest upewnienie się, że czytniki ekranu mogą ogłaszać paski i ich wartości procentowe.

Pracujemy z dwoma różnymi wykresami w jednym: wykresem pokazującym wartości „Szacunkowe”, a drugim pokazującym wartości „Rzeczywiste”. Byłoby wspaniale, gdyby użytkownik wiedział, który pasek jest ogłaszany, więc oznaczmy go symbolem aria-label atrybut:

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

Zauważ, że mamy również wartość paska bezpośrednio w kodzie HTML. Zostanie to ogłoszone, ale nadal chcemy to ukryć wizualnie. Moglibyśmy użyć transparent tekst do tego, ale innym sposobem jest użycie klasyczny .visually-hidden sztuczka owijając wartość w 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;
}

Chociaż mówimy o ogłaszaniu treści, prawdopodobnie możemy zapobiec odczytywaniu etykiet osi Y. To nie tak, że użytkownikowi brakuje informacji, ponieważ rzeczywiste wartości procentowe dla każdego słupka są już dostępne i ogłoszone. Możemy użyć aria-hidden atrybut do tego:

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

Myślę też, że czytniki ekranu mogą ignorować legendę, ponieważ jest to pomoc wizualna:

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

Ostateczne demo

To okład!

Zaczynamy, wykres z nakładającymi się słupkami! To fajny sposób na porównywanie danych i mam nadzieję, że znajdziesz dla niego zastosowanie w jakimś projekcie.

Czy są inne sposoby, w jakie moglibyśmy do tego podejść? Oczywiście! Wszystko, co tu omówiliśmy, jest jedynie przewodnikiem po moim procesie myślowym. Wyobrażam sobie, że niektórzy z was przyjęliby inne podejście — jeśli tak, proszę podziel się! Byłoby wspaniale zobaczyć inne techniki układu CSS i perspektywy na temat dostępności.

Znak czasu:

Więcej z Sztuczki CSS