Generic First CSS: Neues Denken bei Mobile First
Veröffentlicht: 2022-03-10Ich denke, man kann mit Sicherheit sagen, dass Ethan Marcottes Responsive Web Design eine willkommene Offenbarung für Webentwickler auf der ganzen Welt war. Es löste eine ganz neue Welle des Designdenkens und wunderbare neue Front-End-Techniken aus. Auch die Herrschaft der oft verachteten m-Punkt-Websites war vorbei. In derselben Zeit und fast ebenso einflussreich war Luke Wroblewskis Mobile-First-Methodik – eine solide Verbesserung, die auf Marcottes beeindruckenden Grundlagen aufbaute.
Diese Techniken bilden die Grundlage für das Leben der meisten Webentwickler und sie haben uns gute Dienste geleistet, aber leider ändern sich die Zeiten und Entwickler wiederholen sich ständig. Wenn wir die Effizienz unserer Methoden steigern und die Projektanforderungen komplexer werden, entstehen neue Frustrationen.
Die Reise zum ersten Generikum
Ich kann nicht genau sagen, was mich dazu gebracht hat, die Art und Weise, wie ich mein CSS schreibe, zu ändern, weil es für mich wirklich eine natürliche Entwicklung war, die fast unbewusst geschah. Rückblickend denke ich, dass es eher ein Nebenprodukt der Entwicklungsumgebung war, in der ich arbeitete. Das Team, mit dem ich zusammengearbeitet habe, hatte einen netten SCSS-Workflow mit einem raffinierten kleinen Mixin zum einfachen Hinzufügen von Haltepunkten in unseren CSS-Deklarationen. Sie verwenden wahrscheinlich eine ähnliche Technik.
Dieses wundervolle kleine SCSS-Mixin machte es plötzlich einfach, supergranulare Medienabfragen zu schreiben. Nehmen Sie einen hypothetischen Biografieblock, der ungefähr so aussieht:
.bio { display: block; width: 100%; background-color: #ece9e9; padding: 20px; margin: 20px 0; @include media('>=small') { max-width: 400px; background-color: white; margin: 20px auto; } @include media('>=medium') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }
Abb.1. Typisches Mobile First mit kaskadierenden Medienabfragen
Das funktioniert gut – ich habe in der Vergangenheit viele CSS dieser Art geschrieben. Eines Tages dämmerte mir jedoch, dass das Überschreiben von CSS-Deklarationen bei zunehmender Gerätebreite einfach keinen Sinn machte. Warum eine CSS-Eigenschaft deklarieren, damit sie nur in der folgenden Deklaration überschrieben wird?
Dies hat mich dazu veranlasst, mit dem Schreiben von unterteilten Medienabfragen zu beginnen, im Gegensatz zu dem häufigeren Ansatz von Medienabfragen, die nach oben (oder unten) kaskadieren, wie im Beispiel in Abb. 1.
Anstatt Medienabfragen zu schreiben, die mit zunehmender Bildschirmgröße nach oben kaskadieren, habe ich damit begonnen, gezielte Medienabfragen zu erstellen, die Stile bei gewünschten Bildschirmbreiten einkapseln. Das Media-Query-Mixin würde hier wirklich zur Geltung kommen. Jetzt sehen meine SCSS-Medienabfragen so aus:
.bio { display: block; width: 100%; padding: 20px; margin: 20px 0; @include media('>=small', ' < medium') { max-width: 400px; margin: 20px auto; } @include media('>=medium', ' < large') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large', ' < huge') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }
Abb.2. Ein Beispiel für unterteilte Medienabfragen
Dieser neue Ansatz fühlte sich für mich einfach intuitiver an, er reduzierte das Zurücksetzen von Stilen vom vorherigen Haltepunkt und machte das CSS leichter lesbar. Noch wichtiger war, dass die Medienanfragen auf signifikantere Weise selbstdokumentierend wurden.
Ich war immer noch nicht 100% zufrieden mit dem Obigen, aber es schien, als gäbe es noch ein großes Problem zu lösen.
Das Problem mit Mobile First
Das Problem mit Mobile First ist, dass Sie per Definition höchstwahrscheinlich Mobile-First-Stile in nachfolgenden Medienabfragen überschreiben müssen. Das fühlt sich ein bisschen wie ein Anti-Pattern an.
Also – für mich – lag die Antwort auf der Hand: Lassen Sie uns die Idee der Unterteilung von Medienanfragen zu ihrem logischen Abschluss bringen – wir werden auch die mobilspezifischen Stile in ihre ganz eigenen Medienanfragen untergliedern. Ich weiß, ich weiß, das geht gegen die allgemeine Konvention, die wir im Laufe der Jahre gelernt haben. „Mobile First“ ist so allgegenwärtig, dass es normalerweise eine der „Fähigkeiten“-Fragen ist, die ein Personalchef stellen wird. Also muss doch jede Alternative falsch sein, oder? Dies ist normalerweise der Teil, an dem die Leute den Kopf schütteln, während sie immer und immer wieder Mobile First sagen.
Okay, also werden wir das Mobile-First-Dogma durchbrechen und alle unsere Stile in die relevanten Medienanfragen unterteilen. Was uns jetzt bleibt, sind reine generische Stile, die in einem CSS-Selektor deklariert sind, wobei alle anderen gerätespezifischen Stile in Medienabfragen eingekapselt sind, die nur für die relevanten Bildschirmabmessungen gelten. Wir haben jetzt Generic First CSS :
.bio { display: block; width: 100%; @include media('>=0', ' < small') { padding: 20px; margin: 20px 0; } @include media('>=small', ' < medium') { max-width: 400px; margin: 20px auto; } @include media('>=medium', ' < large') { max-width: 600px; padding: 30px; margin: 30px auto; } @include media('>=large', ' < huge') { max-width: 800px; padding: 40px; margin: 40px auto; } @include media('>=huge') { max-width: 1000px; padding: 50px; margin: 50px auto; } }
Abb. 3. Ein Beispiel für Generic First CSS
Ja, es gibt etwas mehr Medienabfragen, aber ich sehe das als Vorteil, jeder Entwickler kann sich jetzt dieses CSS ansehen und genau sehen, welche Stile bei jeder einzelnen Bildschirmgröße angewendet werden, ohne den kognitiven Aufwand, Medien auseinandernehmen zu müssen. Abfragespezifität.
Dies kann großartig für Personen sein, die mit der Codebasis nicht vertraut sind, oder sogar für Sie!
Wann man nicht aufteilen sollte
Es gibt immer noch Zeiten, in denen die Unterteilung von Medienabfragen eine Belastung darstellt, und in einigen Fällen ist eine gute alte >= Medienabfrage in Ordnung. Denken Sie daran, dass wir nur versuchen, das Überschreiben von Eigenschaften zu vermeiden.
Dev-Tool Bliss
Eine wichtige unbeabsichtigte Folge des Schreibens von kompartimentiertem Generic First CSS ist die Erfahrung, die Sie aus dem Style-Panel Ihres Entwicklertools ziehen werden. Ohne die Medienabfragekaskade haben Sie jetzt einen klareren Überblick darüber, welche Stile angewendet werden – Sie haben kein Stilfenster voller durchgestrichener Deklarationen von überschriebenen Medienabfrageregeln – Das Rauschen ist weg! Das ist – für mich – einer der größten Vorteile der Generic-First-CSS-Technik. Es bringt ein wenig mehr Vernunft in das CSS-Debugging-Erlebnis, und das ist Gold wert. Dank mir später.
Auswirkungen auf die Leistung
All diese Vorteile von Generic First CSS klingen also ziemlich gut, aber ich denke, es gibt eine letzte Schlüsselfrage, die meiner Meinung nach angegangen werden muss. Es geht um das Thema Leistungsoptimierung. Jetzt weiß ich es noch nicht genau, aber ich habe eine Ahnung, dass vollständig unterteilte Medienabfragen einen leichten Leistungsvorteil haben können.
Browser führen eine Rendering-Aufgabe aus, die als berechnete Stilberechnung bezeichnet wird. Auf diese Weise berechnet der Browser, welche Stile zu einem bestimmten Zeitpunkt auf ein Element angewendet werden müssen. Diese Aufgabe wird immer beim ersten Laden der Seite ausgeführt, kann aber auch ausgeführt werden, wenn sich der Seiteninhalt ändert oder wenn andere Browseraktionen stattfinden. Jeder Schub, den Sie der Geschwindigkeit des Prozesses geben können, ist großartig für das anfängliche Laden der Seite und könnte sich auf den Lebenszyklus der Seiten Ihrer Website auswirken.
Zurück zum generischen ersten CSS: Gibt es Leistungsprobleme im Zusammenhang mit dem Browser, der die CSS-Spezifität einer Vielzahl von kaskadierenden Medienabfragen ermitteln muss?
Um dies zu beantworten, habe ich einen Testfall entwickelt, der verwendet werden kann, um Geschwindigkeitsvorteile oder -nachteile zu messen.
Der Testfall
Der Testfall besteht aus einer einfachen HTML-Seite, die einen „Bio“-Block 5000 Mal ausgibt, das Markup ist für jeden Block gleich, aber die Klassen sind leicht unterschiedlich (numerisches Unterscheidungsmerkmal), das CSS für diesen Block wird ebenfalls 5000 Mal ausgegeben , wobei sich nur die Klassennamen unterscheiden. Das ausgegebene CSS wird durch ein Tool namens CSS MQPacker geleitet. Dies trägt dazu bei, die Dateigröße von CSS, das viele Inline-Medienabfragen verwendet, drastisch zu reduzieren, indem alle separaten Instanzen einer bestimmten Medienabfrage zu einer kombiniert werden. Es ist ein großartiges Tool, das wahrscheinlich davon profitieren wird modernste CSS-Codebasen — Ich habe es als eigenständiges CLI-Tool über eine npm-Aufgabe im Testprojekt package.json verwendet, Sie können es auch als postcss-Plugin verwenden, was schön und praktisch ist!
Der erste Testfall ist ein Mobile-First-Beispiel für kaskadierende Medienabfragen, der zweite Testfall ist eine generische erste unterteilte Variante des CSS. Das CSS für diese Fälle ist etwas ausführlich und könnte wahrscheinlich viel prägnanter geschrieben werden, aber es dient wirklich nur als grobes Beispiel, um die Argumentation zu testen.
Der Test wurde 20 Mal für jede CSS-Variante in Desktop Google Chrome v70 durchgeführt, kein riesiger Datensatz, aber genug, um mir eine ungefähre Vorstellung von einem Leistungsgewinn/-verlust zu geben.
Die von mir gewählten Testmetriken sind:
- Gesamte Seitenladezeit
Eine grundlegende Metrik zum Überprüfen der Seitenladezeit mithilfe der Performance-API-Markierungen am Anfang von <head> und ganz am Ende von <body> - Der Neuberechnungsstil
Zeit aus dem Leistungsbereich der Entwicklungstools. - Das gesamte Seiten-Rendering
Zeit aus dem Leistungsbereich der Entwicklungstools.
Ergebnistabelle (alle Zeiten in Millisekunden)
Mobil zuerst | Allgemein zuerst | ||||||
---|---|---|---|---|---|---|---|
Ladezeit | Stile berechnen | Gesamte Renderzeit | Ladezeit | Stile berechnen | Gesamte Renderzeit | ||
1135 | 565.7 | 1953 | 1196 | 536.9 | 2012 | ||
1176 | 563,5 | 1936 | 1116 | 506.9 | 1929 | ||
1118 | 563.1 | 1863 | 1148 | 514.4 | 1853 | ||
1174 | 568.3 | 1929 | 1124 | 507.1 | 1868 | ||
1204 | 577.2 | 1924 | 1115 | 518.4 | 1854 | ||
1155 | 554.7 | 1991 | 1177 | 540.8 | 1905 | ||
1112 | 554.5 | 1912 | 1111 | 504.3 | 1886 | ||
1110 | 557.9 | 1854 | 1104 | 505.3 | 1954 | ||
1106 | 544.5 | 1895 | 1148 | 525.4 | 1881 | ||
1162 | 559.8 | 1920 | 1095 | 508.9 | 1941 | ||
1146 | 545.9 | 1897 | 1115 | 504.4 | 1968 | ||
1168 | 566.3 | 1882 | 1112 | 519.8 | 1861 | ||
1105 | 542.7 | 1978 | 1121 | 515.7 | 1905 | ||
1123 | 566.6 | 1970 | 1090 | 510.7 | 1820 | ||
1106 | 514.5 | 1956 | 1127 | 515.2 | 1986 | ||
1135 | 575.7 | 1869 | 1130 | 504.2 | 1882 | ||
1164 | 545.6 | 2450 | 1169 | 525.6 | 1934 | ||
1144 | 565 | 1894 | 1092 | 516 | 1822 | ||
1115 | 554.5 | 1955 | 1091 | 508.9 | 1986 | ||
1133 | 554,8 | 2572 | 1001 | 504.5 | 1812 | ||
Durchschn | 1139,55 | 557.04 | 1980 | 1119.1 | 514.67 | 1903.15 |
Abb.6. 20 Testläufe zur Messung der wichtigsten Last-/Rendering-Metriken von Mobile First vs. Generic First CSS.
Aus meinem zugegebenermaßen kleinen Datensatz scheint mein anfänglicher Verdacht richtig zu sein. Im Durchschnitt sehe ich, dass die Aufgabe zur Stilneuberechnung 42 ms weniger Zeit in Anspruch nimmt, was einer Geschwindigkeitssteigerung von 7,6 % entspricht, und daher verringert sich auch die Gesamtrenderzeit. Der Unterschied ist nicht überwältigend, aber es ist eine Verbesserung. Ich denke nicht, dass der Datensatz groß genug ist, um zu 100 % schlüssig zu sein, und der Testfall ist ein wenig unrealistisch, aber ich bin sehr froh, dass ich keinen Leistungsabfall sehe.
Ich wäre sehr daran interessiert zu sehen, wie die generische First-Methodik auf eine real existierende Codebasis angewendet wird, die auf Mobile-First-Weise geschrieben wurde – die Vorher-Nachher-Metriken wären für die tägliche Praxis viel realistischer.
Und wenn jemand Vorschläge hat, wie man diesen Test über einen breiteren Satz von Iterationen automatisieren kann, lass es mich bitte in den Kommentaren wissen! Ich würde mir vorstellen, dass es ein Tool geben muss, das das kann.
Fazit
Um die Vorteile dieser neuen Entwicklungsmethodik noch einmal zusammenzufassen...
- CSS, das genau das tut, was beabsichtigt ist, kein Nachdenken;
- Selbstdokumentierende Medienabfragen;
- Eine bessere Erfahrung mit Entwicklungstools;
- Seiten, die schneller gerendert werden.
Ich würde gerne glauben, dass ich nicht die einzige Person bin, die sich für das Schreiben von CSS in diesem Stil einsetzt. Wenn Sie bereits die generische erste Denkweise angenommen haben, hurra! Aber wenn nicht, denke ich, dass Ihnen die Vorteile, die es mit sich bringt, wirklich gefallen werden. Ich persönlich habe sehr von der übersichtlichen Erfahrung mit den Entwicklertools profitiert, was für viele Entwickler ein großer Vorteil sein wird. Der selbstdokumentierende Charakter dieser Art, Ihre Medienanfragen zu schreiben, wird auch für Sie selbst und das gesamte Team (falls vorhanden) von Vorteil sein. Und schließlich kosten Sie diese Vorteile nichts in Bezug auf die Leistung und haben tatsächlich gezeigt, dass sie marginale Geschwindigkeitsgewinne bringen!
Letztes Wort
Wie alle Entwicklungsmethoden ist es vielleicht nicht jedermanns Sache, aber ich habe mich ganz natürlich für Generic First CSS entschieden. Ich sehe es jetzt als eine wertvolle Arbeitsweise, die mir alle Vorteile von Mobile First mit einigen positiven neuen Ergänzungen bietet die harte Arbeit der Front-End-Entwicklung ein wenig einfacher.
Ressourcen
Testfall-Repo
Wenn Sie den Testfall starten und selbst ausprobieren möchten, finden Sie ihn auf GitHub. Ich würde gerne einige Berichte von anderen sehen.
Werkzeuge
- CSS-MQPacker
- Medien einschließen