Am Limit von CSS, trotz Flexbox und Grid
Friday, 8. June 2018
Eine neue Funktion auf pc-kombo brachte mich entweder an die Limits von CSS, oder zumindest bedurfte es mehr Kenntnisse in den Gebieten Flexbox und Grid als ich besitze.
Der Hardwareempfehler basiert ja im Kern auf einem Meta-Benchmark. Den hatte ich vor nicht zu langer Zeit verbessert und auch als Liste veröffentlicht, er ist eigenständiger Teil der Seite geworden und wird nicht mehr nur intern zum Zusammenstellen der Empfehlungen benutzt.
Der Benchmarkliste fehlte aber eine übliche Funktion: Einzelne Prozessoren bzw Grafikkarten auswählen zu können und nebeneinander zu vergleichen. Im Bild oben ist diese Auswahl schon zu sehen, denn gestern habe ich sie hinzugefügt.
Das Auswählen ist ziemlich witzlos, per Javascript baue ich da auf Knopfdruck das Formular zusammen, das die Vergleichsseite aufruft. Bei der scheiterte ich aber im Detail daran, das gewünschte Design umzusetzen. Dabei ist das an sich nicht kompliziert: Für jeden Vergleichskandidaten gibt es einen Listeneintrag. Diese sollen horizontal nebeneinander gestellt werden. Jeder Listeneintrag hat fünf Bestandteile: Name, Preis, Benchmarkergebnis, Spezifikationen, Detail-Ergebnisse der Einzelbenchmarks. Und hier kommts: Diese können unterschiedlich lang sein, sollen aber über alle Vergleichskandidaten hinweg auf gleicher Höhe anfangen. Aber eben auch: Passen die Listeinträge nicht alle nebeneinander, sollen sie in einer nächsten Zeile weitergelistet werden.
Wie man bei diesem Grafikkartenvergleich super sehen kann, ist das im bisherigen Design nicht gelungen:
Benchmark Results, der letzte Abschnitt, fängt je nach Länge der Spezifikationsliste mal hier, mal dort an, aber nie auf gleicher Höhe.
Das liegt am genutzten Flexbox. Der Code lautet derzeit:
<ol id="benchmarkCompare"> <li> <section class="name"> </section <section class="performance"> </section ... </li> ... <li> <section class="name"> </section <section class="performance"> </section ... </li> </ol>
Das ist also eine geordnete Liste, jede Grafikkarte ist ein Listeneintrag als li
, in diesem sind die fünf Abschnitte als section
gelistet.
Die ol
hat display: inline-flex
, wodurch viel des Designwunsches automatisch funktioniert: Die li
sind horizontal nebeneinader, noch ein flex-wrap: wrap;
und auch das Umbrechen bei zu vielen Einträgen funktioniert einwandfrei.
Aber die Abschnitte in den Listeneinträgen sind nicht automatisch vertikal nebeneinander. Sie wissen ja nichts voneinander: Nichts verbindet sie, sie selbst sind vertikal geordnet, aber jeder Listeneintrag macht diese Ordnung autonom. Flexbox kann das schlicht nicht.
Grid könnte das besser. Mit Grid kann ich sagen: ol
hat display: grid
. Das hat 5 Reihen, die alle auf gleicher Höhe anfangen: grid-template-rows: auto auto auto auto auto
. Es kann dynamisch so viele Spalten erstellen wie nötig: grid-template-columns: repeat(auto-fit, 400px)
. Aber: Die li
, die spielen jetzt keine Rolle, ich will ja die Sektionen in ihnen in das Grid kriegen. Das geht auch: display: contents
, und schon werden die Eltern-li
ignoriert und es sind die section
s, die vom Grid geordnet werden.
Nochmal aber: Die Reihenfolge war falsch. Vom Grid wurden die einzelnen Abschnitte nicht untereinander angeordnet, sondern durch die Listeneinträge durchgewechselt. Also muss die Reihenfolge manuell angegeben werden:
#benchmarkCompare .name { grid-row-start: 1; } #benchmarkCompare .performance { grid-row-start: 2; } #benchmarkCompare .comparePrice { grid-row-start: 3; } #benchmarkCompare .specs { grid-row-start: 4; } #benchmarkCompare .benchmarks { grid-row-start: 5; }
Das funktioniert, alle Abschnitte starten auf gleicher Höhe! Und doch ist diese Lösung komplett unbrauchbar, denn: Sie ist nicht responsiv. Da dieser Code fest angibt, in welcher Zeile welcher Abschnitt sein soll, werden alle Listeneinträge nebeneinander gepackt, ohne dass Umbrüche möglich sind. Ist der Bildschirm dann schmaler als die Liste, müsste der Seitenbetrachter seitlich scrollen – allerdings wurden da bei mir an den Seiten auch Teilbereiche verdeckt, die trotz aktiviertem Scrollbalken nicht mehr erreichbar waren. Das Design bräuchte ein grid-wrap: wrap
, das Pendant zur flexbox, das aber existiert nicht.
Oft braucht Grid das wohl nicht. In den Beispielen funktioniert das einfach, mit erstaunlich wenig CSS. Diese Beispiele müssen aber nie durch display: content
Elternelemente aus dem Grid heraushalten, und sie müssen auch nie(?) die Reihenfolge der Kindelemente angeben. Kombiniert man diese Anforderungen, scheint mein Design einfach nicht möglich zu sein.
Ich lasse mich gerne korrigieren: Übersehe ich etwas? Oder ist CSS-Grid tatsächlich komplett unbrauchbar, da unresponsiv, wenn man etwas so simples wie Unterelemente einer Liste ausrichten will? Würde subgrid diese Probleme lösen, und welchen Zweck erfüllt grid ohne subgrid, wenn es solche einfachen Layouts nicht umsetzen kann?
Ist mit dem per grid umsetzbaren Tabellenlayout das Limit etwa schon erreicht?