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.

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

Den detaillierten Browser-Support für dieses Feature könnt ihr auf caniuse.com einsehen.

Data on support for the css-display-contents feature across the major browsers from caniuse.com

Geschrieben von Jonas

Benutzerbild

Jonas ist Gründer der Agentur kulturbanause und des kulturbanause Blogs. Er arbeitet an der Schnittstelle zwischen UX/UI Design, Frontend und Redaktion und hat zahlreiche Fachbücher und Video-Trainings veröffentlicht. Jonas Hellwig ist regelmäßig als Sprecher auf Fachveranstaltungen anzutreffen und unterstützt mit Seminaren und Workshops Agenturen und Unternehmen bei der Planung, der Gestaltung und der technischen Umsetzung von Web-Projekten.

Jonas Hellwig bei Xing

Feedback & Ergänzungen – 6 Kommentare

  1. digital instinct
    schrieb am 20.08.2018 um 18:52 Uhr:

    Hi Jonas,

    vielen Dank für das zusammenstellen dieses Artikels. Deine Infos haben uns echt geholfen für einen Kunden exakt die gewünschte UI umzusetzen. Zum Glück handelte es sich um eine interne Webanwendung und der Kunde hatte erstmal nur Wert auf Chrome gelegt ;)

    Antworten
  2. Klaus
    schrieb am 16.07.2018 um 09: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.

    Antworten
  3. Homepage
    schrieb am 29.04.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.

    Antworten
  4. Sven
    schrieb am 06.04.2018 um 08: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.

    Antworten
    • Jonas Hellwig
      schrieb am 06.04.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.

      Antworten
    • Matthias
      schrieb am 20.04.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).

      Antworten

Kommentar zu dieser Seite

Wir freuen uns über Anregungen, Ergänzungen oder Hinweise zu Fehlern. Wir lesen jeden Eintrag, veröffentlichen aber nur, was den Inhalt sinnvoll ergänzt.

Website-Projekte mit kulturbanause

Wir wissen wovon wir reden. Wir realisieren komplette Projekte oder unterstützen punktuell in den Bereichen Design, Development, Strategy und Content.

Übersicht Kompetenzen →

Schulungen von kulturbanause

Wir bieten Seminare und Workshops zu den Themen Konzept, Design und Development. Immer up-to-date, praxisnah, kurzweilig und mit dem notwendigen Blick über den Tellerrand.

Übersicht Schulungsthemen →