Der folgende Beitrag stammt von Tom Genoni. Tom wird uns die Denkweise und den Prozess hinter der neuen UI-Bibliothek / dem Sass-Framework von Optimizely vorstellen. Teil 2 von Daniel O’Connor befasst sich mit einigen technischen Aspekten und Integrationsdetails.
Als ich anfing, an Webprojekten zu arbeiten, wurden Stylesheets als notwendiges Übel betrachtet. Es war weder eine *echte* Sprache, die von einem Informatiker ernst genommen wurde, noch einfach genug, damit ein Designer sie vollständig beherrschen und verstehen konnte. Bei wenigen Best Practices war die Organisation von CSS immer ad hoc – „Schriftstile in diesem Abschnitt, Farben in diesem Abschnitt“ – und jede Firma machte es anders. Aber als Webanwendungen und die Teams, die sie entwickelten, immer größer und komplexer wurden, wurde es schwieriger, die explodierenden Codebasen zu verwalten und gleichzeitig die Konsistenz über Teams und Projekte hinweg zu wahren.
Eines der ersten beliebten CSS-Frameworks, das zur Bewältigung dieses Problems aufkam, war Bootstrap. Viele ähnliche Frameworks folgten, aber der Zweck war immer derselbe: Anstatt jedes Mal CSS von Grund auf neu zu schreiben, beginnt man mit einem gestylten Satz der gängigsten Komponenten – Grids, Buttons, Formularelemente, Breadcrumbs –, die browserübergreifend kompatibel sind und leicht zu größeren Interfaces kombiniert werden können.
Bei Optimizely haben wir unser eigenes Sass-Framework namens OUI (ausgesprochen wie das französische Wort für „ja“) entwickelt und pflegen es aktiv. Es basiert auf der Arbeit unzähliger Mitglieder der Web-Community, darunter Mark Otto, Jonathan Snooks, Nicole Sullivan und Harry Roberts, sowie auf den Philosophien von skalierbarem, objektorientiertem CSS und HTML, die von BEM und SMACSS vertreten werden.
Die fortlaufenden Ziele von OUI sind es, Code bereitzustellen, der...
- Abstrahiert. Komponentennamen sollten nicht aus dem Inhalt abgeleitet werden, den sie enthalten. Klassennamen sollten strukturelle Bedeutung vermitteln.
- Wiederverwendbar. Komponenten sollten generisch genug sein, um sie auf der gesamten Website wiederverwenden zu können. Sie sollten keine Annahmen darüber treffen, auf welcher Seite/Ansicht sie verwendet werden. In einem Bereich gelöste Probleme sollten leicht anderswo angewendet werden können.
- Kombinierbar. Komponenten sollten miteinander kombiniert werden können, um größere Blöcke zu erstellen.
- Mit Variablen betrieben. Alle gängigen Designelemente – Farben, Schriften, Abstände, Schatten – sollten mithilfe vordefinierter Variablen definiert werden.
- Skalierbar. Die Wiederverwendung von Mustern bedeutet, dass neue Elemente schneller und mit minimalem zusätzlichem CSS erstellt werden können.
- Konsistent. Entwickler können den Code des anderen besser lesen und tragen zu zuverlässigeren Endnutzererlebnissen bei.
- Klein und DRY. Da wir Low-Level-Komponenten wiederverwenden, um größere Objekte zu erstellen, reduzieren wir CSS-Bloat. Weniger Code bedeutet weniger Fehler.
In diesem Beitrag werde ich die praktischen Schritte und die Partnerschaften mit Ingenieuren und Designern erörtern, die zu seiner Erstellung erforderlich waren, sowie einige Probleme, auf die wir dabei gestoßen sind. In Teil II wird mein Kollege Daniel O’Connor, ein weiterer UI-Ingenieur, die technischen Details beschreiben, wie wir ihn testen, versionieren und in Projekte integrieren.
Phase 1: Holen Sie Ihre Designer mit ins Boot
Die wohl wichtigste Phase bei der Erstellung einer UI-Bibliothek ist die enge Zusammenarbeit mit Ihrem Designteam. Das Designen mit einem Framework erfordert oft eine Verlagerung des Arbeitsablaufs weg von Pixel-perfekten Mockups und kann zu einem scheinbaren Verlust an Designfreiheit führen. Glücklicherweise gibt es einen Weg, dies anzugehen: Auditieren Sie Ihre Website und präsentieren Sie Ihre Ergebnisse.
Widmen Sie ein oder zwei Tage dem Erstellen von Screenshots Ihrer Website. Durchsuchen Sie jeden Winkel nach allen Vorkommen von Buttons, Formularen, Tabellen, Schriftgrößen, Farben, Tags, Icons usw. und gruppieren Sie sie. Was Sie wahrscheinlich aufdecken werden, wird Ihre Designer erschrecken lassen: Buttons aller Formen und Größen, Überschriften mit wenig Regelmäßigkeit, 27 Blautöne und viele andere Beispiele für gut gemeinte, aber schlecht umgesetzte Ideen. Wenn Sie Ihre Designer für die Konsolidierung dieser Inkonsistenzen verantwortlich machen, werden sie zu Partnern bei der Erstellung des Frameworks und Verbündeten bei der Mobilisierung anderer für diese Anstrengung.
Phase 2: Zuständigkeit für das Frontend
Entscheiden Sie mit Ihrem Engineering-Team, wer für das visuelle Frontend „zuständig“ ist. Da die CSS und das HTML Ihres Frameworks miteinander verbunden sind, haben wir festgestellt, dass es wichtig ist, eine kleinere Gruppe zu haben, die mit den Mustern des Frameworks vertraut ist und dafür verantwortlich ist, Code an oft dankbare Ingenieure zu liefern, die sich nicht mehr mit widerspenstigen z-Indizes herumschlagen müssen.
Bei Optimizely sind es unsere UI-Ingenieure, die offiziell Teil des Designteams sind, die diese Rolle ausfüllen. Mit dieser engeren Kontrolle haben wir die Menge an neu zu schreibendem CSS drastisch reduziert, unser Code ist sauberer und konsistenter, und wir erleben weitaus weniger Fehler. Im Laufe der Zeit kann die Verantwortung für das Schreiben von HTML und CSS erweitert werden, wenn Ingenieure verstehen, wie sie die Bibliothek effektiv nutzen können, und wenn das Framework reift.
Phase 3: Identifizieren Sie Ihre Komponenten
Bootstrap enthält so ziemlich alles, was Sie zum Erstellen der meisten Websites benötigen. Aber vielleicht möchten Sie keine Breadcrumbs, oder vielleicht können Sie neuere CSS-Eigenschaften verwenden, da Ihre Browserunterstützung dies zulässt. In jedem Fall empfehlen wir, bestehende Frameworks zu referenzieren und eine Liste nur der Komponenten zu erstellen, die zur Abdeckung Ihrer Anwendungsfälle erforderlich sind. Indem Sie es selbst erstellen, identifizieren Sie potenzielle Problemstellen leichter und lernen dabei eine Menge.
OUI wurde mit nur den Komponenten und Variablen erstellt, die wir als universell bestimmt haben. Jedes Optimizely-Projekt, das OUI verwendet, fügt benutzerdefinierten CSS-Code darauf aufbauend hinzu, nur im Repository dieses Projekts. Dies ermöglicht es jedem Projekt, seine individuellen Designanforderungen zu erfüllen und OUI gleichzeitig schlank und unverändert zu halten. Wenn verschiedene Projekte ähnliche Komponenten einführen, haben wir die Möglichkeit, sie in OUI zu „graduieren“, obwohl dies selten vorkam. In Teil II beschreiben wir unser Integrations- und Versionssystem detaillierter.
Phase 4: Organisieren & Bauen
CSS-Präprozessoren waren ein Segen für die Organisation von Code, indem sie Teil-Dateien unterstützten, die nur das enthielten, was für eine bestimmte Komponente benötigt wurde. Aber es bleibt eine Herausforderung zu entscheiden, wie Dinge benannt und wohin sie platziert werden sollen. Mit OUI verwenden wir derzeit die folgende Struktur
- elements: Mixins und Funktionen. Da wir node-sass für die Kompilierung verwenden, fügen wir auch die Mixins ein, die wir für Animationen, Tönungen und Präfixe benötigen, die normalerweise von Compass stammen würden.
- base: Resets und minimale HTML-Elementstile (Links, Tabellen, Listen)
- components: Low-Level-Elemente, die beim Erstellen von Objekten helfen (Grid, Media, Nav)
- objects: Die vollständig geformten und gestylten Stücke (Buttons, Spinner, Dropdown)
- trumps: Hilfsklassen für das Layout (Margen, Abstände, Schriftstil)
Im Sass verwenden wir keine IDs, die Selektor-Tiefe wird auf ein Minimum beschränkt, und die Quellreihenfolge hilft uns, die Spezifität niedrig zu halten. Sie können einen genaueren Blick in das OUI-Repository werfen.
Phase 5: Dokumentieren & Verbreiten
All diese Arbeit wird nicht dazu beitragen, Ihren Code zu optimieren, wenn niemand davon weiß oder wie man ihn benutzt. Hier sind einige Vorschläge, die OUI geholfen haben, bei Optimizely an Zugkraft zu gewinnen.
- Wählen Sie einen Codenamen. Wie jedes gute Ingenieursprojekt sollte Ihr Framework einen internen Codenamen haben. Es ist wahrscheinlich nichts, was man normalerweise bei CSS-Projekten macht, aber hey, dieses ist wichtig! Wenn es kurz genug ist, kann es als Präfix für die Benennung von Klassen verwendet werden.
- Bieten Sie gute Dokumentation. Wie jeder, der es versucht hat, weiß, ist das Schreiben und vor allem das Pflegen guter Dokumentation mit Codebeispielen, Nutzungshinweisen und einem Changelog nicht einfach. Unvollständige oder veraltete Dokumentation wird Ihre Entwickler nur frustrieren und kann das Vertrauen in das Projekt untergraben. Um dem entgegenzuwirken, benennen Sie Besitzer und legen Sie klare Erwartungen fest, was dokumentiert werden soll und wie es zugänglich und aktuell gehalten wird.
Dies ist eine fortlaufende Herausforderung für uns, aber wir nähern uns langsam an. Daniel O’Connor war unzufrieden mit den bestehenden Lösungen und hat die Entwicklung eines robusten Live-Styleguide-Skripts namens ScribeSass geleitet, das Kommentare und Code in Sass-Quelldateien parst und Codebeispiele rendert. Wir werden das bald als Open-Source-Projekt veröffentlichen.
- Verbreiten. Mit Ihrem prägnanten Codenamen und der Dokumentation beginnen Sie, die Kunde zu verbreiten. Halten Sie Tech-Talks mit realen Beispielen, die die Geschwindigkeits- und Konsistenzvorteile der Wiederverwendung bestehender Stile und Muster demonstrieren. Wenn Sie das Budget dafür haben, erstellen Sie Aufkleber, T-Shirts oder Poster. Sammeln Sie jeden Monat Statistiken über die Größe, Regeln und Spezifität Ihres CSS sowie die Anzahl der Fehler und die Zeit, die Ihr Team mit deren Behebung verbracht hat, und teilen Sie die Ergebnisse. Wir sahen Rückgänge in allen Bereichen.
Erkenntnisse
Wie bei jedem Webprojekt haben wir unterwegs viele Fehler gemacht, Korrekturen vorgenommen und Ergänzungen hinzugefügt. Hier sind einige der Herausforderungen, denen wir uns gestellt haben, Anpassungen, die wir vorgenommen haben, und Probleme, mit denen wir uns weiterhin auseinandersetzen.
- Namensräume. OUI funktionierte gut für neue Projekte, aber als wir anfingen, bestehende Projekte zu refaktorieren, erkannten wir, dass es zu Namenskollisionen bei Klassennamen kommen könnte. Um dies zu vermeiden, haben wir die Option einer namensraumbasierten Sass-Variable hinzugefügt, die den meisten Klassen in der endgültigen CSS-Ausgabe ein Präfix hinzufügt. Wenn zum Beispiel „oui-“ der Wert des Namensraums ist, wird die Klasse „.media“ zu „.oui-media“. Dies gab uns die Flexibilität, OUI freier mit Legacy-Code zu mischen.
- Versionierung. Eine Zeit lang waren wir nicht überzeugt, dass der Aufwand für die Einführung einer formalen Versionierung die Mühe wert war. Nur wenige Projekte nutzten OUI und wir wollten die Hürden für Änderungen nicht zu hoch machen. Aber das Ausliefern von Korrekturen – insbesondere von solchen, die Brüche verursachen könnten – und die Kommunikation ihrer Auswirkungen wurde problematisch. Wir entschieden uns für die Einführung der Semantischen Versionierung, und mit Hilfe eines gut gepflegten Changelogs und einiger Gulp-Pakete können wir Funktionen hinzufügen und Fehler beheben, ohne Angst haben zu müssen, Projekte zu beeinträchtigen, die OUI verwenden. In Teil II wird Daniel O’Connor die Einrichtung der Versionierung detaillierter erläutern.
- Sass-Mixins vs. Extend. Anfangs wurde OUI mit einer beträchtlichen Anzahl von extends eingerichtet. Wir waren uns ihrer Fallstricke bewusst und führten sie vorsichtig ein, immer mit Platzhaltern. Aber die Verwendung von extends kann CSS-Klassen auf unerwünschte Weise verschieben, und trotz unserer besten Bemühungen hatten wir schließlich einige Probleme mit Quellreihenfolge und Spezifität. Wir entschieden uns, viele der extends in Mixins umzuwandeln, und obwohl es etwas mehr Code ist, sind wir weniger besorgt über zukünftige Fallstricke.
- Responsivität. Dies ist knifflig. Wir haben Media-Query-Mixins und optionale Breakpoints für einige unserer Muster, wie z. B. Grids, integriert. Da jedoch so vieles am responsiven Design zwangsläufig komplex ist und oft viel benutzerdefinierten Code erfordert, kann OUI über die grundlegenden Bausteine hinaus nicht viel mehr bieten. Trotz dieser inhärenten Herausforderung werden wir weiterhin Wege evaluieren, um das Framework responsiv freundlich zu gestalten.
- Benutzerdefinierte vs. wiederverwendbare Muster.
Bei der Erstellung neuer Designs und Layouts, die auf einem Spektrum zwischen der Wiederverwendung eines bestehenden Musters und einem völlig kundenspezifischen liegen, liegt es am UI-Ingenieur zu entscheiden, wie diese am besten erstellt werden. Letztendlich ist das Ziel des Aufbaus einer UI-Bibliothek, Ihre CSS-Codebasis so klein und überschaubar wie möglich zu halten, aber Sie müssen auch die Anforderungen und die Flexibilität berücksichtigen, die Ihre Marke und Produkte erfordern. Kann das Design leicht angepasst werden, um in ein bestehendes Muster zu passen? Wenn dies nicht der Fall ist, sollte es sich um ein neues Muster handeln oder ist es völlig einzigartig? Die Verhandlung darüber ist mehr Kunst als Wissenschaft und unterstreicht die Bedeutung von Zusammenarbeit und Kompromissen zwischen Designern und UI-Ingenieuren. - Halten Sie sich daran. Mit der Zeit ist es leicht, Standards schleifen zu lassen. Ein paar hartcodierte Werte und magische Zahlen hier und da werden Ihre Anwendung nicht zum Absturz bringen. Da jedoch viele CSS-Fehler aus den unbeabsichtigten Folgen von vor langer Zeit geschriebenem Code entstehen, ist es wichtig, diese kleinen Zeitbomben fernzuhalten. Diese Disziplin wird sich auszahlen.
Ergebnisse bisher
Obwohl der folgende Vergleich nicht ganz „Äpfel mit Äpfeln“ ist, stammen diese CSS-Statistiken* von zwei visuell ähnlich komplexen Produkten bei Optimizely. Das erste ist eine ältere Anwendung, die vor OUI entwickelt wurde, und das zweite nutzte ausschließlich OUI.
| Produkt ohne OUI | Produkt mit OUI | Ändern | |
|---|---|---|---|
| Gzip-Größe | 101 KB | 33 KB | -68% |
| Stylesheet-Größe | 618 KB | 193 KB | -69% |
| Regeln | 3259 | 1757 | -46% |
| Selektoren | 5183 | 2407 | -54% |
| Identifikatoren | 21375 | 4009 | -81% |
| Deklarationen | 9356 | 4429 | -53% |
| Spezifität pro Selektor | 87 | 15 | -83% |
| Top-Selektor-Spezifität | 641 | 50 | -92% |
| ID-Selektoren | 3135 | 0 | -100% |
* Die meisten Werte wurden mit Parker, einem „Stylesheet-Analyse-Tool“, generiert.
Zusammenfassung
Die Verwaltung eines Frameworks in Ihrem Unternehmen, sei es durch Forken eines bestehenden oder durch eigenes Schreiben, kann entmutigend sein. Aber für Design- und Engineering-Teams, die die Konsistenz zwischen Projekten wahren wollen, sind die Vorteile zu zahlreich, um sie zu ignorieren. Durch die Nutzung vordefinierter Muster erhalten Sie Einheitlichkeit in Optik und Code, schnellere HTML-Erstellung, weniger Fehler, weniger CSS-Bloat und es ermöglicht Produkt-Designern, weniger Zeit mit Spezifikationen und mehr Zeit mit den größeren Herausforderungen der Benutzererfahrung und Informationsarchitektur zu verbringen.
Vielen Dank für das Teilen von OUI und auch dafür, dass Sie Ihre Ziele und Implementierungswege darin aufgenommen haben.
Nur eine Kleinigkeit, die mir aufgefallen ist: Sie scheinen die Bedeutung von „objects“ und „components“ umgekehrt zu haben, verglichen mit der Art und Weise, wie z. B. Harry Roberts sie verwendet, und damit auch OOCSS (objects als abstrakte, wiederholbare, strukturelle Muster). Verwenden Sie sie wirklich andersherum (warum?) oder hat sich das nur im Artikel vermischt?
Hallo Valentin, danke für den Kommentar. Ja, sie sind umgekehrt zu Roberts’ Verwendung. Ich erinnere mich nicht mehr, wann wir die Entscheidung getroffen haben, aber für mich scheint sein Ansatz rückwärts zu sein. Ich denke bei einer Komponente an einen „Teil oder ein Element eines größeren Ganzen“, während Objekte eher vollständig geformt sind, oft aus Komponenten bestehen.
Ich sehe OOCSS als eine Philosophie, die die Wiederverwendung von Code fördert, Inhalte von Containern trennt und Dinge DRY hält. Aber ich würde einer Mannschaft, die die spezifischere OOCSS-Definition, die Sie erwähnt haben, und den damit verbundenen Namensansatz übernimmt, nicht widersprechen.
Hallo Tom, danke für die Klarstellung. Ja, ich verstehe Ihre Sichtweise. Obwohl ich OOCSS als Methodik liebe, denke ich, dass der Name „object“ eine unglückliche Wahl war … aber ich habe mich damit abgefunden ;) Da auch „Components“ mehrdeutig ist, müssen wir uns wohl damit abfinden, dass Begriffe projekt-/methodologieabhängig definiert werden.
Das scheint eine sehr interessante Bibliothek zu sein. Sie benötigt jedoch gute Dokumentation, damit andere sie nutzen können.
Vielen Dank für das Teilen. Ich weiß, dass dies Zeit kostet, und es ist wertvoll, die Bestätigung zu finden, dass die Entwicklung eigener Frameworks immer noch ein valides Konzept ist, und auch zu lesen, wie und warum Sie das getan haben, was Sie getan haben.
Ich habe in den letzten 15 Jahren alle CSS-Hacks, kurzfristigen Lösungen und Polyfills vermieden, die ich vermeiden konnte (sehr selten verwendet). Und wenn neue Technologien in CSS erschienen, habe ich mich darauf gefreut, sie nutzen zu können, ohne Angst haben zu müssen, Kunden-Websites zu beeinträchtigen.
Außerdem hat mich diese Philosophie davor bewahrt, Hunderte von Websites neu gestalten zu müssen, wenn sich CSS-Frameworks in Versionen änderten (Foundation, Bootstrap usw.).
Ich habe festgestellt, dass im Laufe der Jahre fast jedes bekannte Website-Design grundlegende Strukturen hat, die, je einfacher das CSS zur Definition dieser Strukturen ist, desto einfacher sie zu bearbeiten, zu erweitern und zu verbessern sind. Und keines der aktuellen beliebten Frameworks ist einfach.
Das bedeutet, dass Designer gezwungen sind, eine sehr große und komplexe CSS-Bibliothek wirklich zu verstehen, und die Investition bedeutet, dass sie bei zukünftigen Änderungen an der Bibliothek eingeschränkt sind oder Gefahr laufen, diese Investition zu verschwenden.
Da ich noch nie ein Layout mit mehr als 3 Spalten gesehen habe, scheint ein Grid-System, das mehr als das anzeigt, übermäßig kompliziert und verschwenderisch. Und in den seltenen Fällen, in denen sie benötigt werden, funktioniert benutzerdefiniertes CSS bestens.
Ich hoffe, mehr benutzerdefinierte Frameworks aus dem ausdrücklichen Grund zu sehen, dass ich großartige, einfache Lösungen liebe, von denen wir allgemeine langfristige Ziele übernehmen können, kundenspezifische Lösungen, die Sinn ergeben, und Philosophien, die das Design in einer unübersichtlichen technischen Welt zu einer Freude machen.
Prost!