Der folgende Beitrag ist ein Gastbeitrag von Jon Yablonski. Jon wird uns ein Beispiel zeigen, wie wir die Struktur so gestalten können, dass eine Komponente besonders vielseitig ist. Sie funktioniert wie sie ist und hat eine standardisierte Methode zur Erstellung von Variationen (durch Hinzufügen einer einzigen Klasse), die es ermöglicht, das Design an die jeweilige Situation anzupassen.

Die Zeiten, in denen Webseiten mit fester Breite aus pixelgenauen Photoshop-Dateien erstellt wurden, sind vorbei. Um flexible Layouts zu erstellen, die sich intelligent an jede Bildschirmgröße anpassen, haben sich unsere Arbeitsabläufe iterativer und agiler gestaltet. Wir haben die Bedeutung von Modularität erkannt und wie sie die Flexibilität ermöglicht, die wir benötigen, um im Browser agil zu bleiben. Als Designer und Frontend-Entwickler ist diese Flexibilität für meine Herangehensweise an Webprojekte unerlässlich. Ich treffe Designentscheidungen immer häufiger im Browser als in Design-Dateien, und um diesen Workflow zu unterstützen, benötige ich die Fähigkeit, Benutzeroberflächenmodule zu erstellen, die einfach erweitert werden können.
Erweiterbare Module
Was ich sehr schätze, ist Erweiterbarkeit, ein Prinzip des Systemdesigns, bei dem die Implementierung zukünftiges Wachstum berücksichtigt. Das zentrale Thema der Erweiterbarkeit ist, Veränderungen zu ermöglichen und gleichzeitig die Auswirkungen auf das bestehende System zu minimieren. Für die Frontend-Entwicklung bedeutet dies, Modulvariationen zu erstellen, die leicht erweitert werden können, um den Anforderungen der Benutzeroberfläche gerecht zu werden, während die zugrunde liegende Basis des Moduls erhalten bleibt. Das Endergebnis ist weniger Code-Ballast, weniger Fragmentierung der Codebasis durch Einzellösungen und leichter zu wartender Code.
Für Erweiterbarkeit entwickeln
Um die Konsistenz der Struktur unserer Komponenten und Muster zu gewährleisten, müssen wir sie auf eine Weise entwickeln, die wiederholbar und vorhersehbar ist. Im Folgenden sind die grundlegenden Schritte aufgeführt, die ich unternehme
Schritt 1: Modultyp identifizieren
Der erste Schritt besteht darin, den Typ des Moduls zu identifizieren, mit dem wir arbeiten, was in eine von zwei Kategorien eingeteilt werden kann: Komponente oder Muster. Eine Komponente ist ein unabhängiges, modulares Objekt, das keine untergeordneten Elemente hat, aber Modifikatorzustände aufweisen kann, die ihr Aussehen ändern (Beispiel: Buttons, Nachrichten, Thumbnails). Ein Muster hingegen ist ein Objekt, das untergeordnete Elemente hat (die auch eigenständige Komponenten sein können), die alle vom übergeordneten Objekt beeinflusst werden (Beispiel: Header, Header-Logo, Header-Nav). Sowohl Komponenten als auch Muster können Modifikatorzustände aufweisen, die ihr Aussehen oder ihre Struktur ändern.
Schritt 2: Fundament des Moduls definieren
Der nächste Schritt ist die Definition der grundlegenden Regeln der Komponente oder des Musters, die alle Variationen der Komponente erben werden. Diese Regeln sollten relativ minimal gehalten und für Eigenschaften reserviert werden, die sich selten ändern. Meistens sind dies Eigenschaften wie Abstand, Polsterung, Position und Anzeige.
Alle Codebeispiele in diesem Artikel verwenden die BEM-Namenskonvention (Block, Element, Modifier). BEM bietet eine Reihe von Vorteilen, aber vielleicht ist mein Favorit, dass ich allein anhand des Namens erkennen kann, was ein Stück Markup tut. Wenn Sie mehr über diese Namenskonvention erfahren möchten, empfehle ich Ihnen, diesen Artikel für eine gute Einführung.
HTML-Fundament
<div class="block"></div>
CSS-Fundament
.block {
position: relative;
margin: 0 0 1em;
}
Schritt 3: Gemeinsame Elemente definieren
Wenn Sie eine Komponente erstellen, überspringen Sie diesen Schritt und gehen Sie direkt zum nächsten über; wenn Sie jedoch ein Muster erstellen, das untergeordnete Elemente enthält, besteht der nächste Schritt darin, gemeinsame Elemente zu definieren. Diese Elemente stehen thematisch in Beziehung zum übergeordneten Block (können aber auch außerhalb des Musters als eigenständige Komponenten existieren).
Gemeinsame HTML-Elemente
<div class="block">
<div class="block__element">…</div>
<div class="block__another-element">…</div>
</div>
CSS
.block__element {
padding: 1em;
background: white;
border: 1px solid black;
}
.block__another-element {
position: absolute;
top: 0;
right: 0;
}
Schritt 4: Mit Modifikatoren erweitern
Der letzte Schritt besteht darin, Ihre Komponente/Ihr Muster mit Modifikatoren zu erweitern. Modifikatoren sind im Wesentlichen Variationen, die den grundlegenden Block und die untergeordneten Elemente erweitern und nach Bedarf erstellt werden können.
Beispiel für eine HTML-Modifikatorklasse
<div class="block block—modifier">
<div class="block__element">…</div>
<div class="block__another-element">…</div>
</div>
Beispiel für CSS-Modifikation
.block—modifier {
border-top: 3px solid red;
}
.block—modifier .block__element {
background: grey;
}
Beispiele
Nachdem wir uns die grundlegenden Schritte zur Erstellung erweiterbarer Komponenten und Muster angesehen haben, ist es an der Zeit, einige Beispiele zu untersuchen. Wir beginnen mit einer relativ einfachen Komponente und wie sie erweitert werden kann, um eine Vielzahl von Szenarien abzudecken, und dann betrachten wir ein etwas komplexeres Muster.
Über Komponenten
Im Folgenden finden Sie eine Demo mehrerer gängiger Komponenten mit Variationen. Jede Komponente besteht aus einem übergeordneten Block und Modifikatoren, die den Stil des Blocks erweitern. Dies ermöglicht die schnelle Erstellung von Variationen und gibt Ihnen die Flexibilität, Komponenten schnell zu iterieren und an jede Situation in Ihrer Benutzeroberfläche anzupassen.
Beispiel für gängige Komponenten
Sehen Sie den Pen Gemeinsame erweiterbare Komponenten von Jon Yablonski (@jonyablonski) auf CodePen.
Komponenten sollten naturgemäß relativ einfach sein, da sie keine untergeordneten Elemente enthalten. Nun schauen wir uns etwas Komplexeres an.
Über Muster
Ein Medienmuster ist ein Objekt, das aus einem Medienelement (dies kann ein Bild oder Video sein) und zugehörigem Inhalt (in der Regel in Form von Text) besteht. Sie sind vielleicht mit einer Variante des Medienmusters vertraut, die als „Media Object“ oder „Flag Object“ bekannt ist, auf die wir gleich eingehen werden. Dieses Muster ist ein großartiges Beispiel dafür, wie die Entwicklung mit Blick auf Erweiterbarkeit endlose Flexibilität bietet.
Standard-Medienmuster
Wir beginnen mit unserem Standardmuster, also damit, wie es ohne Modifikatoren angezeigt wird. Ich habe hier einige Annahmen getroffen, indem ich ein <article>-Tag verwendet habe, um semantischere Informationen bereitzustellen, aber dies kann durch jedes beliebige Tag ersetzt werden. Die Kernstile unseres Medienmusters sind
- Ein Flex-Container, dessen Kinder nicht umgebrochen werden
- Ein bisschen Rand
Dies sind Stile, die alle Medienmuster erben werden. Darüber hinaus wird jedes Medienmuster das Medienelement (in diesem Fall ein Bild) und den Medienkörper enthalten, der aus einem Titel und einer Definitionsliste besteht.
Sehen Sie den Pen Standard-Medienmuster von Jon Yablonski (@jonyablonski) auf CodePen.
Medienkartenmuster
Während diese Standardvariante unseres Medienmusters unter Umständen ausreichend sein mag, wird es viele andere geben, bei denen Sie sein Aussehen drastisch ändern möchten. Der nächste Schritt besteht darin, Variationen zu identifizieren, die es unserem Muster ermöglichen, sich an verschiedene Situationen anzupassen. Beginnen wir mit einer Variation, die keine große Abweichung vom Standardaussehen darstellt – einer Kartenvariante. Die Prämisse ist, dass sich nur sehr wenig an unserer Struktur ändern muss und wir das Aussehen unseres Musters ändern können, indem wir einfach eine Modifikatorklasse zum übergeordneten Block hinzufügen.
Sehen Sie den Pen Medienkartenmuster von Jon Yablonski (@jonyablonski) auf CodePen.
Media-Objektmuster
Nehmen wir an, ich habe später festgestellt, dass ich ein Muster benötige, bei dem das Bild und der Text nebeneinander angezeigt werden, wenn genügend Platz vorhanden ist. Dies ist ein Muster, das allgemein als „Medienobjekt“ bekannt ist. Um es zu erstellen, können wir einfach das bereits vorhandene Medienmuster erweitern, um redundanten Code zu minimieren.
Sehen Sie den Pen Media-Objektmuster von Jon Yablonski (@jonyablonski) auf CodePen.
Media Slat-Muster
Lassen Sie uns die Dinge noch etwas weiter treiben mit einer Variante, die wirklich auf die Probe gestellt wird. Die bisher definierten Varianten decken ziemlich gut alle meine Designbedürfnisse ab, aber ich brauche noch eine mit etwas mehr Wirkung. Lassen Sie uns eine Variante erstellen, die sich über die gesamte Fensterbreite erstreckt, wobei der Körper die Hälfte und das Bild die andere Hälfte einnimmt. Darüber hinaus möchte ich sicherstellen, dass der Inhalt des Körpers mit dem anderen Inhalt auf der Seite ausgerichtet ist. Wir nennen diese Variante „Media Slat“.
Sehen Sie den Pen Media Slat-Muster von Jon Yablonski (@jonyablonski) auf CodePen.
Jetzt haben wir mehrere Varianten unseres Medienmusters: die Standardvariante, die Kartenvariante, die Objektvariante und schließlich die Slat-Variante. Diese Varianten unseres Musters sind unter verschiedenen Umständen nützlich und alle nutzen die gleiche zugrunde liegende Codebasis! Das Tolle daran ist, dass jede Änderung an unserem Muster alle Muster beeinflusst, sodass jede Instanz dieses Musters synchron und konsistent bleibt.
Fazit
Wir haben abgedeckt, warum erweiterbare Komponenten und Muster beim Erstellen von Benutzeroberflächen besser sind, mit Fokus auf Flexibilität und Wartbarkeit. Und um dies zu veranschaulichen, haben wir die Schritte zur Erstellung einiger erweiterbarer Komponenten behandelt. Die Vorteile der Erstellung von Benutzeroberflächen auf diese Weise werden sich sofort zeigen, da Sie weniger Zeit mit Refactoring aufgrund unerwarteter Designänderungen oder -ergänzungen verbringen und Ihre Styling-Elemente, aus denen diese Komponenten bestehen, einfacher zu warten sind.
Gleich und gleich gesellt sich gern!
Ich arbeite gerade an einem CSS-Framework, das die gleichen Gedanken verfolgt wie Sie.
Großartig! Klingt super interessant.
Was ist die Idee hinter der Verwendung von zwei Unterstrichen für Klassennamen?
Sie können über diese großartige Artikel über die BEM-Namenskonvention lesen.
Gut gemacht. Genial…!!!
Hey, toller Artikel, manchmal fühlt es sich an, als wäre das für „einfache“ Dinge übertrieben, aber es lohnt sich, gute Gewohnheiten zu übernehmen. Ich stecke immer noch in BEM fest.
Die Idee von modularem CSS lässt mich über die Zukunft von CSS kichern. Komponenten und Muster sind eines der Merkmale großartiger Designs. Danke für einen so informativen Artikel.
Sehr gern geschehen, Omeiza!
Wir könnten diese Methodik noch viel weiter bringen, wenn wir Element-/Containerabfragen hätten.
Dem stimme ich voll und ganz zu, Rhys.
Ich benutze diese Methode http://rscss.io
Sieht doch vom Ansatz her ähnlich aus, oder?
Danke für deinen Artikel, Jon! Ich glaube auch, dass das Web aus Komponenten besteht. Meiner Meinung nach hast du BEM falsch angewendet. Du hast Klassen wie
media__body-listundmedia__body-list-title, die meiner Meinung nach nicht zummedia-Block gehören. Wäre es nicht besser, den Monolithen in kleinere Teile zu zerlegen? Ich werde versuchen, dies anhand eines vereinfachten Auszugs aus deinem Code zu demonstrieren.kann werden zu
Somit ist die Medieninformation eine in sich geschlossene Einheit. Und noch mehr, ich vermute, diese Liste hat nichts mit den Medien zu tun.
Ich habe persönlich immer solche Zweifel. Was denkst du dazu?
Ich bin im selben Boot wie du, und dein letztes Beispiel sieht viel sauberer und einfacher zu erweitern aus. Viel zu viele Leute versuchen, die tatsächliche DOM-Struktur in ihre Selektoren zu kopieren.
Interessanter Punkt, Evan, aber ich glaube nicht, dass „Missbrauch“ zutreffend wäre. Es kommt wirklich darauf an, was für Sie am besten funktioniert. Persönlich sehe ich gerne explizit, wie Kinder zum übergeordneten Block gehören. Die Beziehung zwischen Block und Element ist klar („block__element“). Dies ist Teil der Vorteile der Verwendung einer Namenskonvention wie BEM (oder einer Modifikation der Syntax). Das von Ihnen bereitgestellte Beispiel lässt vermuten, dass „media-info“ ein übergeordnetes Element ist und eigenständig existieren kann, was irreführend ist. Ich habe nichts gegen „Monolith“, da die Benennung die Beziehung von Block, Elementen und Modifikatoren sehr deutlich macht.
Meine Entschuldigung, *Ivan.
Hallo Jon! Danke für deine Erklärung! Und meine Entschuldigung, falls ich unhöflich oder so rüberkam. Das Wort „missbraucht“ ist hier definitiv falsch.
Mein Punkt ist, wie Marvin auch erwähnte, manche Entwickler fügen einfach alles hinzu, was sie brauchen, nach
__. So finden Sie vielleicht manchmal solche Klassennamen: :DAus meiner Sicht sollte alles aufgeteilt werden, was wie eine eigenständige Sache aussieht.
Kein Problem, Ivan!
Ich verstehe, was du meinst, aber es sollte beachtet werden, dass Blockelemente andere Blockelemente enthalten können. (zum Beispiel: „media__item item“, „item“ ist auch ein eigenständiger Block).
Der Zweck der Namenskonvention ist es, die Beziehung zwischen Eltern und Kindern klar darzustellen, was ich bei BEM unglaublich hilfreich finde. Auch hier kommt es darauf an, was für Sie funktioniert.
Sehr gut geschriebener Artikel.
Ich bin ein großer Fan von BEM, da es leicht zu lesen ist und gut mit mehreren Entwicklern funktioniert.
Wir verwenden zwei Bindestriche für Modifikatoren, um Elemente zu vermeiden, die mit Bindestrichen versehen sind.
Das Korrigieren der Grundlagen von Anfang an hilft Entwicklern, Projektmanagern und schließlich den Kunden.
Danke, Neil!
Schöner Artikel! Erinnert mich an dieses Buch: https://smacss.com/
Einige Prinzipien ähneln stark dem, was Sie hier schreiben. Sehr interessant für alle, die sich für dieses Thema interessieren. Da ich kein großer Fan der BEM-Notation bin, ziehe ich es vor, Dinge so darzulegen, wie es in diesem Buch geschieht (auch wenn es BEM ähnlich ist; ich mag einfach nicht den doppelten Unterstrich/Bindestrich... Es ist wieder rein persönlich).
Nichtsdestotrotz, interessanter Artikel! Danke!
Wirklich guter Artikel und tolle Beispiele. Ich mag den Wiederverwendungsaspekt davon.
Dies könnte ein gutes Thema für ein zukünftiges Video auf meiner Website sein. Großartige Arbeit, Jon.
Warum wird für Block-Modifikatoren ein langer Bindestrich verwendet? Das ist meiner Meinung nach ein typografischer Fehler. Zwei Bindestriche sollten für die Modifikatorbenennung verwendet werden, ist das richtig?
Hallo Chernenko. Ja, zwei Bindestriche werden für Modifikatorklassen verwendet. Alle Beispiele im Artikel folgen diesem Muster.