kulturbanause Blog

Responsive Design, WordPress, Konzeption, HTML, CSS, JS & UX/UI …

CSS display: contents;

Als Frontend-Designer steht man ab und zu vor dem Problem, dass die semantisch beste HTML-Struktur mit CSS nicht in die gewünschte Form gebracht werden kann. Oft werden daher Abstriche im HTML-Markup in Kauf genommen. Dieser Fall tritt auch dann ein, wenn Layout-Techniken wie Flexbox oder Grid genutzt werden. Mit dem CSS-Befehl display: contents; gehören solche Schwierigkeiten der Vergangenheit an.

Workshops und Seminare von kulturbanause

Visual Prototyping, Responsive Design, CSS Grid & Flexbox, WordPress, Adobe XD, HTML & CSS Grundlagen, Website-Optimierung …

Jetzt Frühbucher-Rabatte sichern!

Beispiel-Layout

Die Funktionsweise von display: contents; lässt sich an einem anschaulichen Beispiel am besten verdeutlichen. Das folgende Layout soll aufgebaut werden:

Beispiel-Layout mit drei »Card-Elementen«, jeweils mit farbigem Header und weißem Inhaltsbereich
Beispiel-Layout mit drei »Card-Elementen«, jeweils mit farbigem Header und weißem Inhaltsbereich

Die Herausforderung besteht darin, dass sowohl alle drei farbigen Header-Bereiche der Cards, sowie auch die drei Inhaltsbereiche gleich hoch sein sollen – auch wenn sie unterschiedlich viel Inhalt besitzen. Aus semantischer Sicht, muss natürlich auch der HTML-Code logisch aufgebaut sein.

Folgender HTML-Code ist gewünscht:

<main class="container">
 
  <section class="box">
    <header class="box-header"> … </header>
    <p class="box-content"> … </p>
  </section>

  <section class="box">
    <header class="box-header"> … </header>
    <p class="box-content"> …</p>
  </section>

  <section class="box">
    <header class="box-header"> … </header>
    <p class="box-content">… </p>
  </section>

</main>

Mit Flexbox und Grid lassen sich nun zwar die drei Boxen (.box) auf eine Höhe bringen, nicht aber die drei Header innerhalb der Boxen. Das hängt damit zusammen, dass die drei Header (.box-header) keine Geschwisterelemente sind, die Boxen hingegen schon.

Einfach wäre es, wenn der HTML-Code wie folgt aussähe und es die umschließenden Boxen nicht gäbe:

<main class="container">
 
  <header class="box-header"> … </header>
  <p class="box-content"> … </p>
 
  <header class="box-header"> … </header>
  <p class="box-content"> …</p>
 
  <header class="box-header"> … </header>
  <p class="box-content">… </p>
 
</main>

Aus semantischer Sicht ist der obige Code zwar inakzeptabel, aber nun lässt sich mit CSS-Grid sehr einfach das Layout konstruieren.

.container {
  display: grid;
  grid-template-rows: auto auto;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-flow: column; 
  grid-gap: 0 1em;
}

Zu Erklärung: Für den .container wird ein CSS Grid mit zwei Zeilen und drei Spalten aktiviert. Die beiden Zeilen haben eine automatische Höhe, wodurch alle .box-header und alle .box-content sich am enthaltenen Inhalt orientieren und immer gleich hoch dargestellt werden. Die drei Spalten haben jeweils eine Breite von 1fr, wodurch auch diese gleich breit dargestellt werden. Mit grid-auto-flow: column; wird festgelegt, dass Elemente spaltenbasiert – von oben nach unten – im Grid angeordnet werden. Der Abstand zwischen den Boxen wird durch grid-gap erzeugt.

Der folgende Screenshot aus den Chrome DevTools visualisiert den Aufbau noch einmal, eine detaillierte Einführung zum Thema CSS Grid findet ihr hier.

Visualisiertes CSS Grid in den Chrome DevTools
Visualisiertes CSS Grid in den Chrome DevTools

Funktionsweise von display: contents;

Das oben beschriebene Beispiel zeigt, dass das gewünschte Layout grundsätzlich sehr unkompliziert ist, allerdings nur wenn Abstriche in der HTML-Semantik gemacht würden. Es versteht sich von selbst, dass wir sowohl die bestmögliche HTML-Semantik als auch ein unkompliziertes CSS-Layout möchten. Genau hier kommt display: contents; ins Spiel.

Wenn display: contents;auf ein Element angewendet wird, werden alle Inhalte des Elements so dargestellt, als gäbe es den öffnenden und den schließende HTML-Befehl des Elements nicht. display: contents; macht daher immer dann besonders viel Sinn, wenn das Element selbst kein sichtbares Styling besitzt.

Genau das ist in unserem Beispiel der Fall. Die drei .box-Elemente, müssen aus struktureller HTML-Sicht vorhanden sein, sollen für das CSS-Layout aber nicht existieren.

Lösung mit display: contents;

Der gewünschte HTML-Code des Beispiels sieht somit wieder wie zu Beginn aus:

<main class="container">
 
  <section class="box">
    <header class="box-header"> … </header>
    <p class="box-content"> … </p>
  </section>

  <section class="box">
    <header class="box-header"> … </header>
    <p class="box-content"> …</p>
  </section>

  <section class="box">
    <header class="box-header"> … </header>
    <p class="box-content">… </p>
  </section>

</main>

Mit angewendetem display: contents; auf den .box-Elementen ist das Layout kein Problem. Die .box-Elemente werden nun vom CSS-Layout ignoriert, wodurch sich alle enthaltenen Elemente (.box-header und .box-content) wie Geschwisterelemente verhalten.

.container {
  display: grid;
  grid-template-rows: auto auto;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-flow: column; 
  grid-gap: 0 1em;
}

.box {
  display: contents;
}

Beispiel anschauen

Browser-Support

display: contents; steht zum Veröffentlichungszeitpunkt des Beitrags in Chrome und Firefox zur Verfügung. In Safari wird der Befehl ab der kommenden Browser-Version verfügbar sein. Microsoft unterstützt den Befehl noch nicht, weshalb ein CSS-Fallback mit @supports sinnvoll ist. Den aktuellen und detaillierten Browser-Support entnehmt ihr bitte der Website caniuse.com.

Jetzt bist du gefragt!

Hast du Anregungen, Ergänzungen, einen Fehler gefunden oder ist dieser Beitrag nicht mehr aktuell? Dann freuen wir uns auf deinen Kommentar.

Du kannst diesen Beitrag natürlich auch weiterempfehlen. Wir sind dir für jede Unterstützung dankbar!

Das könnte dich auch interessieren

5 Kommentare

  1. Sven

    Verfasst am 6. April 2018 um 8:32 Uhr.

    Schönes Beispiel, was sicherlich in der Praxis öfters mal vorkommt. Problem ist natürlich, das display: contents Global nur von 13% der Browser unterstützt wird. Somit muss man aktuell noch anders an die Sach herangehen. Eventuell über eine min-height am header-Element. Das ist natürlich dann nicht so dynamisch.

    • Jonas Hellwig

      Verfasst am 6. April 2018 um 10:57 Uhr.

      Alternativ kann man natürlich auch per JavaScript die Höhe dynamisch anpassen, bis der Browser-Support von display: contents; dann ausreichend ist.

    • Matthias

      Verfasst am 20. April 2018 um 18:13 Uhr.

      Hallo Sven,
      zu aller erst, das Beispiel finde ich sehr gut erklärt. Das nur „13%“ der Browser contents unterstützt ist an sich ja kein Problem. Es nutzt ja so gut wie jeder Chrome / Firefox / Edge (eher weniger).

  2. Homepage

    Verfasst am 29. April 2018 um 17:26 Uhr.

    Hi Jonas,

    danke für die Erklärung. Das wäre genau das Richtige, um ein derzeitiges Problem in einem Webprojekt zu lösen, wenn da nicht die Browserkompatibilität wäre. Wir haben es rein gebaut und lösen den Rest mit dem bereits erwähnten Javascript Hack.

  3. Klaus

    Verfasst am 16. Juli 2018 um 9:39 Uhr.

    Ja, ich wollte das gleiche wie Sven erwähnen – display: content; in einer kleinen Anzahl von Browsern korrekt angezeigt wird, während die Elemente in den meisten Browsern korrekt angezeigt werden.

Kommentar verfassen

Dieser Blog lebt vom Feedback der Besucher! Also los, mach mit!
Bitte habe Verständnis dafür, dass Kommentare die mit dem Inhalt dieses Beitrags nichts zu tun haben, gelöscht werden.