Jeder, der auch nur irgendwie im Alltag mit CSS zu tun hat, ist wohl in den vergangenen Monaten über das Thema Container Queries gestolpert. Sei es auf Social Media oder auf Konferenzen, sie sind in aller Munde, und aktuell führt kein Weg an ihnen vorbei.
Aber wieso redet momentan eigentlich jeder über Container Queries? Was macht sie so mächtig, und warum werden sie die Art, wie wir unsere Projekte in Zukunft – sowohl von Design als auch von Entwicklungsseite – angehen, fundamental verändern?
Schauen wir uns einmal gemeinsam die Erweiterung des CSS-Standards an, die eine neue Ära in Sachen Responsivität und Flexibilität einläutet, beziehungsweise die Ära des Component-Driven Design & Development endgültig vervollständigt und damit gleichzeitig das Ende der sogenannten “Mobile First”-Ära bedeutet.
Der Ursprung des Responsive Web
Beginnen wir aber zunächst am Anfang und schauen uns an, wie Projekte, sowohl von Design- als auch von Entwicklungsseite, in der Vergangenheit strukturiert wurden und wie genau wir da gelandet sind.
Mit der stark zunehmenden Verbreitung von Smartphones Ende der 2000er, beziehungsweise Anfang der 2010er Jahre taten sich im Web große Probleme bezüglich der Adaption gerade dieser auf. Webseiten waren bis zu diesem Zeitpunkt ausschließlich auf Desktop-Geräte ausgelegt und an ein responsive Web, wie wir es heute kennen, war damals gar nicht zu denken.
Big Player wie Meta (ehem. Facebook) und Google waren nahezu die einzigen, die mobile Webseiten auslieferten, was unter anderem an den deutlich eingeschränkten Möglichkeiten, mobile Geräte zu erkennen, lag. Serverseitig wurde anhand des User Agents, welcher im Request Header beim Abfragen der Webseite mitgesendet wurde, differenziert, um welche Art von Gerät es sich handelte, um so eine entsprechende mobile Version der Webseite auszuliefern.
Google nutzt noch heute ein ähnliches Verfahren, so sieht das mobile Layout der Start- sowie Suchergebnisseite deutlich anders aus als die Desktop Version und verhält sich nicht so responsiv, wie man es erwarten würde.
Erst mit dem breiten Support für Media Queries und der damit einhergehenden Adaption öffnete sich das Web immer mehr für diese neue Generation von internetfähigen Geräten, und während der Markt für Desktop Geräte in den kommenden Jahren immer mehr stagnierte, nahm die Verbreitung von anderen internetfähigen Geräten immer mehr zu. Schauen wir heute auf die breite Masse von internet- und, konkret für unseren Fall, browserfähigen Geräten, ist von Smartphones und Smartwatches über Spielekonsolen bis hin zu Kühlschränken alles dabei.
Will man heutzutage ein neues digitales Produkt auf den Markt bringen, kommt man über eine responsive, crossmediale Integration quasi gar nicht mehr herum.
Wieso eigentlich mobile first?
Mit der immer größer wachsenden Gruppe der Smartphone-Nutzer wurde schnell ein Problem deutlich. Es ist schwierig, all die Informationen, welche einem Desktop-Nutzer präsentiert werden, in gleicher Form und Menge an einen Smartphone-Nutzer weiterzugeben. Allerdings sollten letztere natürlich auch nicht in Sachen Funktionalität und Informativität benachteiligt werden. So begann man bereits früh mit dem Fokus auf mobile Geräte zu designen und zu entwickeln. Der “Mobile First”-Ansatz war geboren.
Über die kommenden Jahre festigte sich dieser Ansatz immer mehr und wurde zum Standard für neue Projekte im Web. Heute werden mehr als 50 Prozent aller Seitenaufrufe von einem Mobilgerät getätigt und die Tendenz ist weiterhin steigend.
Warum also sollte man von diesem Ansatz abweichen?
The NEW web
Über die letzten Jahre haben sich Webseiten, sowie Webapplikationen in einem nie dagewesenen Tempo weiterentwickelt – sowohl von Technologie- als auch von Architekturseite.
Große Teile der Architektur wandern in die Cloud, und Edge Hosting & Computing gewinnen immer mehr an Bedeutung.
MACH-Architektur
Eine derzeit sehr weit verbreitete Architektur ist die sogenannte MACH-Architektur. Die einzelnen Buchstaben stehen dabei für:
- Microservices-based
- API-first
- Cloud-native SaaS
- Headless
Wie die einzelnen Begriffe schon vermuten lassen, handelt es sich hierbei um eine äußerst flexible Architektur, welche darauf beruht, einzelne Systeme und Software möglichst kleinteilig und modular betrachtet zu entwickeln, um so eine maximale software- und plattformübergreifende Wiederverwendbarkeit zu gewährleisten.
Um ein solches Maß an Flexibilität zu erzielen, werden Front- und Backend meist entkoppelt voneinander betrachtet und entwickelt.
Design-Systeme
Um trotz neu gewonnener Flexibilität ein einheitliches Bild nach außen zu tragen, setzen die meisten großen Unternehmen auf Design-Systeme.
Dabei handelt es sich um eine einheitliche Sammlung an Komponenten, welche, ebenso wie das dynamische Backend darunter, software- und plattformübergreifend zum Einsatz kommt.
Doch eben dieser, oftmals crossmediale, Einsatz von Komponenten (z.B. Webseite, App) ist der Punkt, an dem viele Design-Systeme Probleme bereiten. Während es für Designer kein Problem ist, Komponenten isoliert zu gestalten, stoßen gerade Entwickler bei der Implementierung von Design-Systemen oftmals an die Grenzen des technisch nativ möglichem.
Responsivität neugedacht
Während Media Queries Anfang der 2010er Jahre ein Segen für eine gesamte Industrie waren und einen maßgeblichen Teil zur Adaption des Smartphones beigetragen haben, stellen sie heute oftmals eine große Hürde für die Einführung von Design-Systemen dar.
Die Grenzen von Media Queries
Doch wo genau liegt eigentlich das Problem bei Media Queries, und warum erweitern wir nicht einfach den Media-Queries-Standard um eine entsprechende Lösung?
Schauen wir uns die Fragen und die dazugehörigen Antworten einmal an, um ein genaueres Bild der Problematik zu bekommen.
Wo liegt eigentlich das Problem bei Media Queries?
Die Antwort liegt hier tatsächlich auf der Hand, denn der Name verrät sie bereits. Media Queries sind, wie der Name es schon sagt, darauf ausgelegt, verschiedene Stylings an Hand von medialen Unterschieden auf unsere Webseite oder Komponenten anzuwenden.
Was passiert allerdings, wenn eine Komponente an verschiedenen Stellen beziehungsweise in verschiedenen Kontexten auf ein und derselben Seite vorkommt? Schauen wir uns die nachfolgende Abbildung genauer an, um das Problem besser zu verstehen.
Zu sehen ist hier ein Wireframe einer herkömmlichen Webseite. Von der reinen Struktur könnte man sagen, es handelt sich um eine Produktübersichtsseite. Schnell erkennt man, dass der Inhalt aller Elemente identisch ist – Bild, Überschrift und Text. Demnach würde es ja durchaus Sinn ergeben, alle diese Elemente über eine Komponente abzubilden und diese abhängig vom Kontext zu stylen.
An dieser Stelle scheitern Media Queries allerdings, da gerade diese kontextuellen Unterschiede bei der Abwägung des Stylings nicht in Betracht gezogen werden können. Schauen wir uns das Ganze einmal an einem konkreten Codebeispiel, analog zur obigen Darstellung, an.
Gegeben ist das folgende Markup einer Produktkachel:
Der bis heute einfachste und schnellste Weg, die Kachel abhängig vom Kontext anzupassen, war, die Stylings an den entsprechenden Kontext zu binden.
Der Sinn eines Design-Systems wäre damit allerdings völlig hinfällig, denn wir haben allein durch diese doch sehr kleine Änderung die Isolation unserer Komponente aufgehoben und ihre Darstellung von anderen externen Faktoren abhängig gemacht und diese gleichzeitig in ihrer Flexibilität eingeschränkt, sowie Fehleranfälligkeit erhöht und Wartbarkeit gesenkt.
Allein das Umbenennen der Klasse .article zu bspw. .tile würde in diesem Fall die kompletten kontext-spezifischen Styles invalidieren. Alles in allem also keine gute Lösung.
Eine bessere und auch entsprechend komplexere Lösung wäre es, die Größe der Komponente mit Hilfe von ResizeObservern zu tracken und Styles abhängig von der dargestellten Größe an das jeweilige Element zu rendern.
Auch wenn diese Lösung auf den ersten Blick alle Probleme aus dem vorherigen Lösungsansatz behoben beziehungsweise umgangen hat, ist leider auch diese in vielerlei Weise problematisch. Zum einen haben wir durch die Verwendung von ResizeObservern ein mögliches Performance-Bottleneck in unsere Seite integriert, welches bei übermäßiger Verwendung zu Problemen auf Kosten der User Experience führen kann. Zusätzlich kann es in speziellen Ausnahmefällen dazu kommen, dass Größenänderungen zu spät oder gar nicht vom ResizeObservern erkannt werden. Zum anderen haben wir durch die erhöhte Komplexität in der Implementierung natürlich auch hier eine geringere Wartbarkeit.
Also weiter zur zweiten Frage:
Warum erweitern wir nicht einfach den Media-Queries-Standard um eine entsprechende Lösung?
Die Antwort auf diese Frage lässt sich tatsächlich ebenfalls aus dem Namen ableiten. Media Queries haben ihren Anwendungsfall in der medialen Differenzierung von Styles. Es ist an dieser Stelle unsere Problemstellung, welche nicht zur von uns ausgewählten Lösung passt.
Allerdings, auch wenn dies Probleme sind, welche seit Jahren existieren, dauerte es bis Anfang dieses Jahres, bis Browser begannen, die lange ersehnte “korrekte” Lösung in Form von Container Queries in ihren Stable Versionen auszurollen.
Schauen wir nun endlich auf das lang angeteaserte Feature, welche Funktionen es mit sich bringt, wie man es verwendet und auf welche Erweiterungen wir uns in Zukunft freuen können.
Was sind denn nun Container Queries?
Container Queries setzen dort an, wo Media Queries ihre Grenzen haben. So erlauben sie es, Elemente abhängig von ihrem Kontext zu stylen und damit nativ, ohne JavaScript und ohne Workarounds, eine Möglichkeit zu schaffen, responsive und wiederverwendbare Komponenten zu implementieren. Eben genau so, wie man es sich für ein echtes Design-System wünscht.
Um genauer darauf einzugehen, was das konkret für unsere Komponenten bedeutet, schauen wir noch einmal auf die Abbildung aus dem Absatz Wo liegt eigentlich das Problem bei Media Queries?, in leicht abgewandelter Form.
Sofort sieht man, da ist ein bisschen mehr Farbe im Bild, aber was genau sollen diese dunkelblauen Boxen zeigen?
Wie im Intro bereits erwähnt, können wir mit Hilfe von Container Queries Elemente abhängig von ihrem Kontext stylen und damit mit Media Queries unlösbare Probleme aus der Welt schaffen. So können wir in diesem konkreten Beispiele entweder die verschiedenen Inhaltsbereiche, sprich Sidebar und Hauptinhalt oder auch die verschiedenen Einzelkacheln, als Container definieren und die Stylings entsprechend der Größe eben dieser anpassen.
Um das Ganze an Hand eines Codebeispiels zu simulieren, schauen wir uns das Beispiel einer Produktkachel aus dem vorherigen Absatz noch einmal an:
Wollen wir die einzelnen Produktkacheln nun mit Hilfe von Container Queries analog zum Beispiel aus Wo liegt eigentlich das Problem bei Media Queries? stylen, sieht das Ganze wie folgt aus:
HTML
CSS
Mit etwas zusätzlichem Styling könnten die Kacheln sich dann wie folgt verhalten:
See the Pen
Example – Container Queries by Quentin Albert (@Quentin_Albert)
on CodePen.
Schnell springen einem gerade im CSS einige Änderungen ins Auge. So haben wir auf unser .productTile neue Styles in Form von container: productTile / inline-size;, sowie einige neue at-rules wie zum Beispiel @container (inline-size > 600px).
Schauen wir uns zunächst die Änderungen an der Klasse .productTile an.
Durch das Setzen von container: productTile / inline-size; definieren wir unser HTML-Element als Root-Element eines neuen sogenannten Containment Contexts und damit gleichzeitig als einen in Container Queries nutzbaren Container.
container: productTile / inline-size; ist hierbei nur die Kurzform der Attribute und Werte container-type: inline-size; und container-name: productTile;.
Während container-name lediglich optional beim Erstellen eines neuen Containers ist, ist der container-type essentiell, um den Browser mitzuteilen, dass und um welche Art von Container es sich handelt (bei Verwendung der Kurzform mittels container sind beide Angaben Pflicht). Dabei wird zwischen folgenden Container-Typen unterschieden:
- inline-size
- size
- normal
Bei inline-size und size handelt es sich um Container Size Query Keywords, sprich um größenbasierte Container Query Arten. inline-Size definiert dabei konkret einen Container, welcher lediglich auf Veränderungen entlang der X- beziehungsweise nach logischem System der Inline-Achse achtet, während Container des Typs size auf Änderungen entlang beider Achsen achten.
Bei normal handelt es sich zum aktuellen Zeitpunkt um das einzige Keyword, welches nicht zu den Container Size Queries gehört, sprich das Setzen von container-type: normal; würde zwar einen neuen Container erstellen, dieser wäre allerdings nicht für die responsive Nutzung gedacht. Welche Use-Cases Container Queries außerhalb von responsiven Anwendungsfällen mit sich bringen und wofür man in diesem Zusammenhang konkret das normal Keyword einsetzen kann, schauen wir uns später im Ausblick an.
Auch wenn es sich bei container-name, wie bereits erwähnt, lediglich um ein optionales Keyword bei der Definition von Container handelt, bringt es neben der rein strukturellen Benennung der Container noch eine weitaus interessantere Funktionalität mit sich, welche sich erst beim genaueren hinschauen auf die Container Query selbst ergibt.
Sehen wir uns dazu einmal die folgende Zeile aus dem vorherigen Beispiel an: @container productTile (inline-size > 900px). Während anonyme Container Queries @container (inline-size > 900px) sich immer auf den nächsten Parent-Container beziehen, können Named Container Queries einen beliebigen Parent-Container referenzieren. Gerade in komplexen Layouts, in denen mehrere Container ineinander geschachtelt sind, kann dies eine sehr mächtige zusätzliche Funktion sein. Ähnlich wie Media Queries kann man Container Queries ineinander schachteln und damit Abhängigkeiten zu mehreren Containern in einer Query darstellen.
Schauen wir uns noch einmal ein Beispiel an, um zu verstehen, in welchen verschiedenen Weisen Container definiert und in Container Queries verwendet werden können.
Container Query Conditions
Neben dem in den vorherigen Beispielen viel verwendeten inline-size gibt es noch einige weitere Container Query Conditions, welche analog zu ihrem Media Query Pendant funktionieren.
Folgende Conditions werden akzeptiert:
- aspect-ratio
- orientation
Die folgenden dimensionalen Conditions existieren alle zusätzlich in den bekannten min- und max- Varianten:
- block-size
- height
- inline-size
- width
Diese können ebenfalls wie bei Media Queries in Kombination mit logischen Operatoren verwendet werden. Konkret sind folgende Operatoren erlaubt:
- and
- or
- not
Container Query Length Units
Um maximale Styling-Flexibilität in Zusammenhang mit Container Queries zu gewährleisten, wurden parallel zur Einführung dieser einige neue Längeneinheiten zum CSS-Standard hinzugefügt. Diese sind speziell auf die Nutzung innerhalb eines Containers ausgelegt. Werden sie allerdings außerhalb eines Containers verwendet, beziehen sie sich auf das Root-Element des DOMs.
Die Container Query Length Units sind ein Pendant zu den oft verwendeten Viewport Units, somit gibt es nun folgende neue Units:
- cqw
- cqh
- cqi
- cqb
- cqmin
- cqmax
Diese Einheiten können in allen CSS-Definitionen verwendet werden, welche den Typ <length> akzeptieren.
Gegenüberstellung
Nachdem wir uns Container Queries zu genüge angeschaut haben, mag man sich die Frage stellen:
“Wofür brauche ich denn jetzt noch Media Queries? Container Queries decken nahezu alle meine Use-Cases ab.”
Obwohl diese Aussage in dem ein oder anderen Projektkontext korrekt sein mag, haben beide Technologien ihre Daseinsberechtigung und sind darauf ausgelegt, in Kombination eingesetzt zu werden.
Wenn wir uns die folgende Darstellung anschauen, sehen wir zudem, dass Container Queries tatsächlich nur einen Bruchteil der Funktionalität von Media Queries abdecken.
Ausblick
Zwar sind Container Queries gerade erst in den Browsern gelandet, allerdings arbeitet die CSS Working Group bereits an einer Erweiterung des Standards in Form von Container Style Queries.
Während wir bis zu diesem Punkt ausschließlich von Container Size Queries gesprochen haben, ergibt sich durch Container Style Queries ein komplett neuer Anwendungsbereich für die Verwendung von Container Queries.
So wird es in Zukunft möglich sein, Styles des Containers abfragen und an Hand von diesen Elemente zu stylen. Konkret wird das ganze so aussehen:
Das zweite Beispiel ist hierbei besonders interessant, da es erlaubt, anhand des Wertes einer Custom Property verschiedene Styles an verschiedenen Elementen zu toggeln, ohne deren Spezifität zu erhöhen.
Dies ermöglicht flexible Konfiguration von Komponenten über natives CSS ohne Verwendung von JavaScript und Properties, wie wir es aus vielen Single Page Application Frameworks kennen, und ist damit ein wahrer Gamechanger.
Verwendet werden kann das Feature an jedem Container, sprich an Size Containern, aber auch an Containern mit dem Container-Typen normal, welchen wir zuvor kurz einmal angerissen hatten, sobald es in allen Browsern verfügbar ist.
Wer das Ganze jetzt schon testen möchte, kann dies bis zu einem gewissen Grad in Chrome tun, dort ist das Feature bereits mit eingeschränkter Funktionalität nutzbar. Speziell kann dort bisher nur auf Custom Properties geprüft werden und nicht auf wahllose Styles des Containers.
Zusammenfassung
Mit der Möglichkeit, Container und Media Queries in Kombination in allen modernen Browsern zu verwenden, tun sich sowohl für Entwickler als auch Designer ganz neue Optionen auf, Responsive und Flexible Layouts und Komponenten zu erschaffen.
Design-Systeme und Komponenten können endlich in der Flexibilität implementiert werden, welche sie schon seit Jahren haben sollten und damit gerade großen Unternehmen viel Zeit und Geld bei der Implementierung von neuen User Interfaces sparen.
Auch wenn Container Queries zum aktuellen Zeitpunkt noch als experimentelle Technologie gesehen werden können, ist es nur eine Frage der Zeit, bis diese sich als fester Bestandteil des heutigen Web etablieren. In Kombination mit Container Style Queries kann zusätzlich viel der heutzutage im JavaScript liegenden visuellen Rendering-Logik zurück ins CSS gebracht und damit vereinfacht werden.
Alles in allem können Webentwickler, aber auch Designer auf eine schöne Zukunft schauen, in der sich die Kommunikationsprobleme zwischen den Parteien, als auch die Komplexität in der Implementierung dezimieren werden.
Zusatz
Die Codebeispiele in diesem Artikel verwenden an einigen Stellen neuere Syntaxen, welche oftmals noch nicht im allgemeinen CSS-Gebrauch angekommen sind.
Hier ein paar Links zu den verschiedenen Themen:
- Sass, Less & Co: Brauchen wir 2024 noch CSS-Präprozessoren? - 6. Februar 2024
- CSS Container Queries – das unabwendbare Ende von “Mobile First” - 18. Juli 2023