Element Queries: Webdesign mit Layouts noch besser gestalten
Mit Media Queries können Webdesigner Style-Angaben an bestimmte Geräteeigenschaften koppeln. Verbunden mit der natürlichen Anpassungsfähigkeit mancher Layoutmodelle wie Floats, Inline-Blocks, CSS-Tabellen und Flexbox lässt sich damit allerlei anstellen. Idealerweise beschreibt man das gesamte responsive Regelwerk einer Webseite.
Doch wie gut harmonieren Media Queries eigentlich mit Konzepten wie Atomic Design? Statt traditionell ganze Seitenlayouts am Stück umzusetzen, geht es bei Atomic Design darum, einen Katalog an Einzelteilen zu bauen, die anschließend beliebig zu neuen Seitenkompositionen re-kombiniert werden können. Eine solche komponentenbasierte Entwicklung ermöglicht einen hohen Grad der Wiederverwendbarkeit von Bausteinen und hilft verhindern, dass das CSS mit einer zunehmenden Anzahl Seitentypen linear mitwächst. Außerdem ermöglichen es Komponentensammlungen, leichter den Überblick über den Arbeitsstand zu behalten und sie erleichtern die Einhaltung von Konventionen wie BEM oder SMACSS. Leider stellt sich heraus, dass CSS Media Queries in solch einem Umfeld eher wenig zu gebrauchen sind. Das klingt erst einmal sehr verwunderlich, aber eine Layout-Aufgabe aus der Praxis legt seine Schwächen offen.
Falsche Freunde
Ein Steckbrief-Modul ordnet in der kompakten Ansicht alle Informationen zu einer Person untereinander an (Abbildung 1). An oberste Stelle haben wir ein Profilfoto, darunter kommen Jobbezeichnung und Abteilung, dann die Kontaktmöglichkeiten. Das Bild und die Texte werden dabei zentriert. Wenn dem
Modul mehr Platz zur Verfügung steht, soll es sich in ein zweispaltiges Layout verwandeln, bei dem das Profilfoto in die linke Spalte und die Textinformationen in die rechte rutschen. Das Bild soll der Optik wegen in seiner Spalte nunmehr rechtsbündig angeordnet sein, die Texte linksbündig.
Üblicherweise würde ein Entwickler nun in das Modul-CSS eine Media Query einfügen, die ab einer gewissen Seitenbreite das zweispaltige CSS aktiviert. Das funktioniert auf den ersten Blick auch ganz tadellos.
Doch nun kommt in der Designabteilung jemand auf die Idee, dass bestimmte Unterseiten der Präsenz in der Desktop-Ansicht mehrspaltig werden sollen. Und dass ein solcher Steckbrief dann in der Marginalspalte einer dieser Seiten zum Liegen kommen soll.
Auf einmal fängt das bisherige Media-Query-Konstrukt an zu bröckeln: Da die Media Query ausschließlich den Viewport in Betracht zieht und nicht den tatsächlich verfügbaren Platz, wendet sie in der Desktop-Ansicht auf das Steckbrief-Modul immer das zweispaltige Layout an.
Das gilt auch dann, wenn das Modul in der Marginalspalte steckt und dort kaum mehr Platz bekommt, als wenn es bildschirmfüllend in einem mobilen Browser zu sehen wäre. Korrekt wäre es, wenn das Modul auch hier in die vertikale Anordnung mit den zentrierten Texten umschalten würde. Mit Floats, Inline-Blocks oder Flexboxen lässt sich das Umbruch-Problem zwar noch lösen, für das Umschalten zwischen den Textbündigkeiten gibt es aber keinen eleganten Kniff.
Ein Ausweg ist nur durch das Hinzufügen sperriger Sonderregeln möglich. Also konkret auf das obige Beispiel bezogen, indem das Modul-CSS um eine Desktop-Media-Query erweitert wird, die alles auf die mobile Ansicht zurückdreht, sobald das Modul innerhalb der Marginspalte steckt. Das funktioniert, ist aber wenig universell und auch nicht robust. Wird das Modul in ein anderes Element verschachtelt, braucht es dafür wieder eine Sonderregel. Und verschiebt sich eines Tages der Breakpoint, ab dem eine Seite mehrspaltig wird, muss diese Änderung auf alle Module übertragen werden, welche in Abhängigkeit zu diesem Spalten-Modul stehen. Zu guter Letzt ist es auch so, dass ein solches Vorgehen gegen die DRY-Prinzipien verstößt. Denn die CSS-Deklarationen für das kompakte Layout müssen ja doppelt hinterlegt werden. Sicherlich helfen Preprozessoren dabei, diese Vorgänge etwas zu entschärfen und besser zu organiseren, aber sehr viel eleganter wird die Lösung des Problems damit trotzdem nicht.
Element Queries: Die Rettung?
Der Lösungsansatz, der hier auf der Hand liegt, sind die sogenannten Element Queries. Über die wird im Umfeld des W3C schon eine ganze Weile debattiert. Besonders viel gedankliche Vorarbeit und auch Lobbyarbeit betreibt diesbezüglich die W3C „Responsive Issues“ Community Group, angeführt von Mat Marquis. Im Prinzip ähneln die Element Queries stark den Media Queries, nur dass sie sich auf das Abfragen von Element-Breiten und -Höhen beschränkt. Ein Syntax-Vorschlag sah zwischenzeitlich so aus:
Syntax-Vorschlag für Element Queries
.profile { overflow: hidden; /* clearfix */ } /* Einspaltig */ .profile-picture, .profile-data { display: block; text-align: center; } /* Zweispaltig */ .profile:media(min-width: 20em) .profile-picture, .profile:media(min-width: 20em) .profile-data { width: 50%; float: left; text-align: left; } .profile:media(min-width: 20em) .profile-picture { text-align: right; }
Listing 1
Nicht nur eine gute Idee, sondern auch einfach anzuwenden! Allerdings stieß der Vorschlag nicht auf die uneingeschränkte Liebe der Browserhersteller, was daran lag, dass es mit den Element Queries auf einmal möglich würde, Endlosschleifen zu erzeugen. Denn folgendes CSS würde den Browser für immer zwischen zwei Zuständen oszillieren lassen:
Endlosschleifen erzeugen
.profile { width: 20em; } .profile:media(min-width: 20em) { width: 10em; }
Listing 2
Auch problematisch sind Anweisungen, die Kind-Elemente betreffen, die aber auf die Breite des Mutterelements durchschlagen. Während das W3C weiter an einer Lösung arbeitet, haben zahlreiche Unerschrockene das Konzept der Element Queries dennoch schon aufgegriffen und es in JavaScript-Bibliotheken gegossen. Eine davon ist der CSS-Element-Queries Polyfill.
CSS-Element-Queries Polyfill
Dieser Polyfill von Marc J. Schmidt aus Hamburg unterscheidet sich von vielen anderen Lösungen dadurch, dass er es ermöglicht, Element Queries im CSS zu beschreiben, anstatt sie per JavaScript oder HTML-Data-Attributen separat vom CSS konfigurieren zu müssen. So findet sich weiterhin all das an einer Stelle versammelt, das mit der Gestaltung eines Elements zu tun hat. Element Query Breakpoints definieren Entwickler im CSS fast genau so, wie weiter oben gezeigt die Element Queries, bloß dass sie das .profile:media(min-width: 20em) auf .profile[min-width~=“20em“] abändern müssen – sie also Attributsselektoren verwenden. Unterstützt werden [min-width], [min-height], [max-width] und [max-height], wobei bei einem „Mobile First“-Ansatz nur [min-width] zum Einsatz kommt.
Was aber, wenn einige Unterseiten die Darstellung wie hier im Bild ändern sollen? Eine Lösung wäre der Einsatz von Element Queries (Abbildung 3). Der Polyfill besteht aus zwei JavaScript-Dateien, die eingebunden werden wollen: ResizeSensor.js überwacht die Elementgrößen und ElementQueries.js sorgt dafür, dass die Element Queries aus dem CSS extrahiert und für die betreffenden Elemente scharf geschaltet werden. Von diesem Moment an wird die Größe dieser Elemente kontinuierlich überwacht, und zwar auf ressourcenschonende Art. Erfüllt die aktuelle Größe die Bedingung einer oder mehrerer definierter Element Queries, fügt der Polyfill im HTML ein „min-width“-Attribut zum Element hinzu und füllt es mit allen aktuell zutreffenden Element Breakpoints.
Das oben gezeigte Steckbrief-Element etwa würde ab 20em Breite mit folgendem Markup aufwarten: <div class=“profile“ min-width=“20em“>. Und dadurch greift dann auch die CSS-Regel, deren Selektor auf .profile[min-width~=“20em“] abzielt. Sind mehrere Breakpoints für ein Element definiert, und treffen mehrere von ihnen gleichzeitig zu, so sähe das HTML zum Beispiel so aus: <div class=“profile“ min-width=“20em 40em 60em“>. Das erklärt dann auch, weshalb Entwickler im CSS min-width~=“20em“ und nicht min-width=“20em“ notieren sollen, denn andernfalls würde keine der Element Queries mehr greifen.
Das einzige, was der Polyfill aktuell nicht kann, ist bei dynamisch per JavaScript (AJAX, React, Angular) zusammengesetzten Seiten zu bemerken, wenn neue Elemente erst später im DOM-Baum auftauchen, für die aber Element Queries vorliegen. Die werden dann nicht automatisch in die Überwachung mit aufgenommen. Es gibt allerdings die Möglichkeit, ihn manuell erneut nach Elementen suchen zu lassen, welche er noch nicht auf dem Radar hat, und zwar über den Befehl „ElementQueries.init(document.body)“.
In Klammern geben Webentwickler den DOM-Knoten an, den der Polyfill in die Tiefe durchforsten soll. Im Falle von „document.body“ würde er den gesamten DOM-Baum durchsuchen. Ist hingegen klar, dass nur an bestimmter Stelle neue Elemente hinzugekommen sind, dann landet in Klammern stattdessen der entsprechende Bereichsknoten. Das erspart dem Polyfill unnötige Arbeit. Wer das Ganze automatisiert haben mag, der kann das DOM mit Hilfe eines sogenannten Mutation Observers überwachen lassen und bei entsprechenden Veränderungen eine Aktualisierung der Element Queries veranlassen. Die Mutation Observer werden ab Internet Explorer 11 unterstützt, für Internet Explorer 9 und 10 gibt es einen Mutation Observer Polyfill.
Obwohl auch der Polyfill Endlosschleifen auslösen kann, passiert das in der Praxis eigentlich nie. Denn die Anweisungen, die dafür notwendig wären, ergeben in der Praxis einfach wenig Sinn und kommen somit auch nie vor. Der Zugewinn durch die CSS-Element-Queries ist aber enorm, gerade dann, wenn man an skalierenden und langlebigen Projekten arbeitet. Element Queries ermöglichen robuste, universell funktionierende Komponenten, deren responsives Verhalten sich neuen Kollegen wie von allein erklärt – ohne, dass man eine Schnitzeljagd durch alle Stylesheets veranstalten muss. Ein Versuch beim nächsten Projekt lohnt sich damit allemal.
Super, vielen Dank für diesen Artikel. Ich würde mir wieder mehr solcher Artikel im T3N Magazin wünschen, die praxisnah und hilfreich in der Webentwicklung sind!
Die Element Queries sind eigentlich das, worauf man wartet – mediaqueries sind viel zu unflexibel.
@Christian Schaefer: setzt Du diese tatsächlich schon zahlreich in Deinen (Live-)Projekten ein? Falls ja: kombinierst Du sie mit den klassischem Mediaqueries oder nutzt Du evtl. nur noch die ElementQueries?
Danke und Gruß, Andreas
Hallo Andreas, hab deinen Kommentar von vor über einem Jahr hier gar nicht registriert. Falls dich die Antwort noch interessiert: Ja, ich nutze diese Technik auch in Alltagsprojekten, und es lohnt sich. Außerdem skaliert es auch mit der Anzahl Elemente Recht gut.
Viele Grüße!
Ganz genau. Element Queries sind lange überfällig, dass vereinfacht das ganze responsive webdesign Thema so erheblich.
Das sollte der feuchte Traum eines jeden Frontend Developers sein.
Das ist es! :)
Wie funktioniert die Anwendung denn genau im optimalen Fall?
Weist man der Seite global für die einzelnen Mediatypes per Mediaquery jeweils eine Basis Schriftgröße (px) zu und definiert das gesamte übrige Verhalten der Seite und der einzelnen Elemente und deren Inhalte abhängig relativ zur geltenden Schriftgröße bzw der daraus resultierenden relativen zur Verfügung stehenden Breiten (em)?
Hallo Marie,
Nein, da bist du, wahrscheinlich aufgrund der verwendeten em-Maßeinheit auf dem falschen Dampfer. Die em sollte man grundsätzlich immer für Media oder Element Queries verwenden, weil so deren Breakpoints proportional zur eingestellten Schriftgröße mitwachsen. Und das ist aus Gründen der Barrierefreiheit wichtig, weil Anwender die Schrift ja von sich aus größer einstellen könnten. Und dann soll sich das Layout ja nicht zerschießen.
Die Breakpoints werden also individuell im Element definiert und interessieren sich nicht für das, was drumherum los ist.
Das Marie war übrigens die autokorrektur, sorry…
Danke!
Gibt es eigentlich ein paar live Beispiele:
Ganze Webseiten?
Codepen o.ä. von einer Teilseite?
Hallo Mafrie,
meine bisher damit gebauten Projekte sind nicht öffentlich zugänglich, daher kann ich Dich nur auf die Demo-Seite der CSS Element Queries Bibliothek verweisen: http://marcj.github.io/css-element-queries/
Geiler Shit! Wann wird sowas von allen Browsern ohne Plugins unterstützt? :D