Diagramme mit CSS erstellen

Avatar of Robin Rendle
Robin Rendle am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Es gibt viele Möglichkeiten, Daten visuell darzustellen: Balkendiagramme, Liniendiagramme, Streudiagramme, Sparklines… ganz zu schweigen von den vielen Möglichkeiten, wie man sie im Web implementieren kann. In diesem Beitrag werde ich mich mit reinen CSS-Methoden zur Gestaltung von Daten befassen. Aber bevor wir uns einige Beispiele ansehen, ist es meiner Meinung nach sinnvoll, zuerst kurz unsere Designziele zu besprechen.

Richtlinien für die Erstellung von Diagrammen

Es gibt drei Leitlinien für die Entwicklung eines Diagramms im Web

  1. Barrierefreiheit: Jeder sollte in der Lage sein, einige Formate der von uns präsentierten Daten anzuzeigen, auch wenn es sich um eine langweilige Tabelle handelt (langweilig ist besser als nichts).
  2. Entwicklungsfreundlichkeit: Die Erstellung von Grafiken sollte nicht unnötig kompliziert sein, und wir werden sicherlich technischen Schulden für die Zukunft vermeiden wollen.
  3. Leistung: Wir müssen sicherstellen, dass die Benutzer nicht viel Zeit mit dem Warten auf den Download von Assets oder das Rendern von Elementen auf dem Bildschirm verbringen.

Diese Ziele werden sich wahrscheinlich je nach Art des erstellten Diagramms ändern, da die Leistung für ein statisches Balkendiagramm weniger relevant ist als für eine verrückte interaktive Karte. Mit diesen Richtlinien im Hinterkopf sehen wir uns nun einige Beispiele an.

CSS-Balkendiagramme

Es gibt verschiedene Möglichkeiten, ein einfaches Balkendiagramm in CSS zu erstellen. Zunächst verwenden wir eine Definitionsliste für unsere Daten

<dl>
  <dt>A title of the graph</dt>
  <dd class="percentage"><span class="text"> Data 1: 20% </span></dd>
  <dd class="percentage"><span class="text"> Data 2: 50% </span></dd>
  <dd class="percentage"><span class="text"> Data 3: 30% </span></dd>
</dl>

Wir werden den Textinhalt jedes dd mit diesem Span links absolut positionieren.

Um die „Balken“ zu erstellen, die die Daten visuell darstellen, werden wir Pseudoelemente verwenden. Dazu könnten wir das Markup mit Klassen wie .percentage-20 aktualisieren und eine Breite auf sein Pseudoelement setzen

.percentage:after {
  content: "";
  display: block;
  background-color: #3d9970;
}
.percentage-20:after {
  width: 20%;
}
.percentage-30:after {
  width: 30%;
}

Aber wir möchten nicht jede einzelne dieser Klassen von Hand schreiben, da sich die Daten in Zukunft wahrscheinlich ändern werden. Wir könnten eine Sass-Schleife schreiben, um all diese Klassen für uns zu erstellen

@for $i from 1 through 100 {
  .percentage-#{$i}:after {
    $value: ($i * 1%);
    width: $value;
  }
}

Das ist *ein wenig* unschön, da es eine ganze Reihe von Klassen erstellt, die wir wahrscheinlich nicht in der endgültigen Implementierung verwenden werden, aber es gibt viele Tools, um dies für uns in der Produktion aufzuräumen.

Als Nächstes können wir diese automatisch generierten Klassen zu jedem .percentage-Element hinzufügen, wie hier

<dl>
  <dt>A title of the graph</dt>
  <dd class="percentage percentage-7"><span class="text"> IE 11: 7% </span></dd>
  <dd class="percentage percentage-20"><span class="text"> Chrome: 20% </span></dd>
  <dd class="percentage percentage-2"><span class="text"> Android 4.4: 2% </span></dd>
</dl>

Schließlich können wir Regeln zum Hintergrund jedes .percentage-Elements hinzufügen, um die Lesbarkeit beim Vergleichen dieser Werte mit einem repeating-linear-gradient zu verbessern

.percentage {
  background: repeating-linear-gradient(
    to right,
    #ddd,
    #ddd 1px,
    #fff 1px,
    #fff 5%
  );
}

Diese Technik ist relativ einfach, aber ich kann nicht anders, als zu denken, dass diese Informationen standardmäßig immer in einer Tabelle hinterlegt sein sollten. Obwohl ich ein wenig beunruhigt bin, Tabellen auf diese Weise zu gestalten, bedeutet das sicherlich nicht, dass es unmöglich ist. Zum Beispiel hat Eric Meyer über diese Technik geschrieben und beschrieben, wie man widerspenstige Tabellenelemente positioniert, damit sie sich wie ein Balkendiagramm verhalten. Dies ist sein ursprüngliches Markup für die Tabelle

<table id="q-graph">
  <caption>Quarterly Results</caption>
  <thead>
    <tr>
      <th></th>
      <th class="sent">Invoiced</th>
      <th class="paid">Collected</th>
    </tr>
  </thead>
  <tbody>
    <tr class="qtr" id="q1">
      <th scope="row">Q1</th>
      <td class="sent bar"><p>$18,450.00</p></td>
      <td class="paid bar"><p>$16,500.00</p></td>
    </tr>
    <tr class="qtr" id="q2">
      <th scope="row">Q2</th>
      <td class="sent bar"><p>$34,340.72</p></td>
      <td class="paid bar"><p>$32,340.72</p></td>
    </tr>
    <tr class="qtr" id="q3">
      <th scope="row">Q3</th>
      <td class="sent bar"><p>$43,145.52</p></td>
      <td class="paid bar"><p>$32,225.52</p></td>
    </tr>
    <tr class="qtr" id="q4">
      <th scope="row">Q4</th>
      <td class="sent bar"><p>$18,415.96</p></td>
      <td class="paid bar"><p>$32,425.00</p></td>
    </tr>
  </tbody>
</table>

Im Gegensatz zu dem Beispiel, das ich zuvor verwendet habe, bei dem ich eine Reihe von automatisch generierten Hilfsklassen in Sass implementiert habe, um die Breite der Balkendiagramme zu definieren, verwendete Eric Inline-Stile auf dem td-Element, wobei die Werte serverseitig oder mit JavaScript berechnet wurden, anstatt von Hand hinzugefügt zu werden.

Das folgende Beispiel ist meine Kopie von Erics Originalbeispiel, bei dem ich die Gestaltung ein wenig aktualisiert habe

Mir gefällt sehr gut, dass jede Zeile in der Tabelle eine Überschrift wie Q1, Q2 usw. hat – das wirkt sehr ordentlich und sauber, anstatt sich auf eine Definitionsliste zur Beschreibung des Inhalts zu verlassen. Sie sind einfach zu positionieren und fallen schön auf eine Standardtabelle zurück, falls die CSS-Formatierung aus irgendeinem Grund fehlschlägt.

Ein Problem bei diesem Ansatz ist jedoch, dass jede Tabellenzeile nebeneinander absolut positioniert werden muss, was bedeutet, dass wir, wenn wir mehr Daten hinzufügen möchten, viel mehr Arbeit haben werden, als einfach nur das Markup zu aktualisieren. Das könnte in Zukunft mühsam sein.

Sparklines

Wir müssen nicht immer Tabellen verwenden, um Informationen wie diese darzustellen. Das ist wahrscheinlich der Fall, wenn wir eine Reihe von Sparklines erstellen, winzige Grafiken, die neben einer Textzeile stehen und den Lesern helfen, einen schnellen Überblick über die Informationen zu bekommen. Wilson Miner hat diese Methode dargelegt und darauf geachtet, die Barrierefreiheit der Informationen im Voraus sicherzustellen

<figure>
  <ul class="sparklist">
    <li>
      <a href="http://www.example.com/fruits/apples/">Apples</a>
      <span class="sparkline">
        <span class="index"><span class="count" style="height: 27%;">(60,</span> </span>
        <span class="index"><span class="count" style="height: 97%;">220,</span> </span>
        <span class="index"><span class="count" style="height: 62%;">140,</span> </span>
        <span class="index"><span class="count" style="height: 35%;">80,</span> </span>
      </span>
    </li>
  </ul>
  <figcaption>Fruits eaten in the last 14 days by type</figcaption>
</figure>

Ich habe das ursprüngliche Markup von dem, was Wilson verwendet hat, aktualisiert, da dies meiner Meinung nach besser in ein figure passen sollte, da die Dokumentation auf MDN besagt, dass

Normalerweise [ein Figure-Element]… ist ein Bild, eine Illustration, ein Diagramm, ein Code-Snippet oder ein Schema, auf das im Haupttext verwiesen wird, aber das ohne Beeinträchtigung des Hauptflusses auf eine andere Seite oder in einen Anhang verschoben werden kann.

Das ergibt für mich mehr Sinn als ein einfaches ul-Element. Aber trotzdem, hier ist, wie das ohne CSS aussieht

Sehr zugänglich! Als Nächstes können wir diese sparkline-Elemente gestalten und sie mit inline-block rechts neben dem Link positionieren. Und wieder könnten wir den Sass-Klassen-Generator verwenden, den wir zuvor benutzt haben, um die Höhe jedes Balkens festzulegen. Aber lassen wir die Stile vorerst einfach inline

Stellen Sie sicher, dass Sie mit der Maus über jeden Eintrag in der Liste fahren, um eine erweiterte Version des Diagramms zu sehen, das ich hinzugefügt habe. Obwohl es in Bezug auf die Aufschlüsselung der Daten nicht besonders hilfreich ist, zeigt es, dass wir nicht auf Diagramme in einer einzigen Darstellung beschränkt sind; die einfache Manipulation dieser Visualisierungen ist ein großer Vorteil bei der Verwendung einfacher Markups und CSS.

CSS-Kreisdiagramme

Lea Verou hat kürzlich einen großartigen Artikel über die Erstellung von Kreisdiagrammen geschrieben. Eine Möglichkeit, die sie vorschlägt, ist die Verwendung von Pseudoelementen, die einen Kreis abdecken und sie mit transform: rotate() verschieben.

Eine weitere Möglichkeit ist SVG, das eine Reihe von Vorteilen bietet, von denen wir einige im nächsten Abschnitt auflisten werden.

Wenn Browser conic-gradient() unterstützen würden, wäre das eine *sehr* überzeugende Methode, sie zu erstellen. Das tun sie noch nicht ganz, aber Lea hat ein Polyfill dafür, das wunderbar funktioniert. Hier ist ein Kreisdiagramm-Demo, das es verwendet und das wir für eine der letzten Umfragen hier auf CSS-Tricks erstellt haben

Probleme bei der Erstellung von Diagrammen mit CSS

  • Wenn Sie background verwenden, um ein Element zu gestalten, ist es (wahrscheinlich) nicht sichtbar, wenn die Webseite gedruckt wird. Die einzige Ausnahme ist, wenn Sie -webkit-print-color-adjust: exact; in einem WebKit-Browser verwenden.
  • Widerspenstige Designkontrolle: die absolute Positionierung von Tabellenzeilen zum Beispiel wird wahrscheinlich irgendwann in der Zukunft ein Problem für Entwickler sein.
  • Die Browserunterstützung ist in einigen Fällen mühsam, und die Sicherstellung, dass alle Geräte jede CSS-Eigenschaft unterstützen, kann schwierig zu testen sein.
  • Es ist nicht möglich, Inline-Stile auf Pseudoelemente anzuwenden. Wenn Sie also ein Pseudoelement mit JavaScript gestalten möchten, wird dies die Dinge etwas komplizierter machen.
  • Es ist möglich, alles mit CSS zu machen, aber wenn wir reine CSS-Liniendiagramme erstellen, sollten wir uns vielleicht etwas Zeit nehmen, um die Auswirkungen auf den Rest der Codebasis zu überdenken.

Zusammenfassung

Reine CSS- und Markup-Lösungen für Diagramme und Grafiken funktionieren bis zu einem gewissen Grad, und in vielen Situationen sind sie wahrscheinlich die sicherste Wahl. Aber ich denke, es lohnt sich, alternative Lösungen zur Darstellung von Daten zu erforschen.

Im nächsten Beitrag dieser Serie werde ich mich mit SVG- und JavaScript-Lösungen zur Erstellung von Diagrammen befassen.

Weitere Informationen