Atomic Design und BEM — Komponentenbasiertes CSS — Teil 2

BEM in Action
  1. Atomic CSS
  2. BEM
  3. Praktisches Beispiel

Beim Programmieren sollte es neben optimaler Funktionalität auch immer um optimale Lesbarkeit und Verständnis gehen.

Je besser Code strukturiert, kommentiert und bezeichnet ist, desto einfacher ist es für andere und für einen selbst, sich im Nachhinein zurechtzufinden.

In diesem Artikel möchte ich aufzeigen, wie man mit Hilfe von BEM nachvollziehbares CSS und nachvollziehbaren Code schreiben kann.


Wie man seinen Code übersichtlich und wiederverwertbar strukturiert habe ich im 1. Teil „Atomic CSS“ behandelt.

Seinen Code zu kommentieren, könnte nochmal ein eigenes Thema hergeben. Kurz zusammengefasst:

„Good code comments itself.“

„Guter Code kommentiert sich selbst“. Allerdings sollte man sich weder komplett darauf verlassen, dass man seinen Code so gut geschrieben hat, dass man keine Kommentare braucht, noch sollte man mehr Kommentare als eigentlichen Code schreiben.

Ein gesundes Mittelmaß ist der Weg, den es auch hier meist individuell zu finden gibt.

BEM ist natürlich nicht die einzige Konvention im großen weiten Internet, meiner Meinung jedoch die praktikabelste. Auf die Alternativen gehe ich am Ende noch einmal kurz ein.


Was ist BEM?

BEM steht für „Block, Element, Modifier“ — zu deutsch (welch Überraschung): „Block, Element, Modfikator“.

Anhand des Namens erkennt man vielleicht schon, warum ich BEM als CSS-Konvention im Zusammenspiel mit Atomic CSS gewählt habe.

Eine vollständige BEM-Klasse wäre dann wie folgt aufgeteilt:

.block__element--modifier

Warum doppelte Trennstriche?

Doppelte Trennstriche werden deshalb verwendet, weil man bei der Namensgebung von BEM auch einfache Trennstriche für ein Segment verwenden kann:

.btn-group

Bei btn-group handelt es sich z.B. schon um einen Block.

Am Besten kann man das Prinzip am Beispiel eines News-Teasers verdeutlichen:

<div class="e-teaser">

<!-- Teaser Headline -->
<div class="e-teaser__head e-teaser__head--highlight">
<h3 class="e-teaser__headline">News Teaser Überschrift</h3>
</div>
  <!-- Teaser Image -->
<div class="e-teaser__image">
<img src="/path/to/image" alt="">
</div>
  <!-- Teaser Content -->
<div class="e-teaser__content">

<p>Lorem Ipsum dolor sit amet...</p>
    <!-- Weiterlesen Link -->
<a href="/" class="e-btn e-btn--primary">
<span class="e-btn__icon"><svg ...></span>
<span class="e-btn__content">Mehr erfahren</span>
</a>
</div>
</div>

Das Beispiel zeigt, was es mit Block, Element und Modifikator auf sich hat: .e-teaser ist der umschließende Block.e-teaser__head erweitert den Block .e-teaser und das Element __head, und .e-teaser__head — highlight modifiziert eine bereits gestylte Klasse .e-teaser__head um sie von anderen Teaser hervorzuheben.

Warum das „e-„ zu Beginn der Klasse?

Das e- zu Beginn der Klasse ist eine Namespace-Erweiterung, die nicht zwingend mit BEM zu tun hat, meiner Meinung nach dennoch sinnvoll ist. Sie dient dazu, dass unsere Klassennamen nicht aus versehen mit den Klassen von JavaScript-Plugins oder CSS-Frameworks in Konflikt geraten.

CSS Frameworks verwenden zwar selten BEM für Klassenbezeichnungen, aber schon wenn der Block modifiziert wird, kann das weitreichende Folgen haben.

Unter Umständen stellt man das nicht sofort fest, und hat dann im Nachgang viel Aufwand bei der Fehlersuche und beim Fixen des Problems.

Man muss nicht unbedingt e- verwenden, hier ist man vollkommen frei.


Machen lange Klassennamen mein CSS nicht noch schwerer lesbar?

Im HTML-Dokument kann das in der Tat recht schnell zu etwas Klassengewirr führen. So kann ein großer, primärer Button wie folgt aussehen:

<a href="/" class="e-btn e-btn--large e-btn--primary">Button</a>

Das ist sowohl eine Stärke als auch eine Schwäche von BEM. Zum einen können wir das Aussehen des Buttons direkt mit Klassennamen beeinflussen (z.B. indem wir e-btn — large entfernen, wird der Button kleiner), zum anderen reihen sich dann Klasse an Klasse.

Wie sieht das im CSS aus?

Precompiler to the rescue!

Ich gehe davon aus, dass kaum noch jemand pures CSS schreibt. Schon vor Jahren haben sich Precompiler wie Sass, SCSS, Less und Stylus zum Standard etabliert, und regelmäßig kommen weitere spannende Erweiterungen dazu, die einem das CSS-Leben erleichtern, wie z.B. PostCSS.

So kann man mit SCSS seine BEM-Klassen sogar sehr übersichtlich schreiben:

/*------------------------------------*\
#TEASER
\*------------------------------------*/
.e-teaser {
$root: &;
  display: block;
float: left;
padding: 20px;
  // Header 
&__head {
padding-bottom: 20px;
}
  // Headline
&__headline {
font-size: 30px;

// Highlighted
&--highlight {
color: $_primary;
}
}
  // Image
&__image {

}
  // Content
&__content {
padding: 20px 0;
    #{$root}--active & {
color: $_primary;
}
}

}

So nutzt man zum einen die semantische Verschachtelung eines Precompilers sowie BEM in seiner Perfektion.

Ausserdem verhindern wir unnötige Verschachtelungen, die es uns schwer machen würden, das Aussehen des Teasers in anderen Komponenten zu modifizieren.

Der erzeugte Code sieht dann genau so aus, wie wir das wollen:

/*------------------------------------*  
#TEASER
\*------------------------------------*/
.e-teaser {
display: block;
float: left;
padding: 20px;
}

.e-teaser__head {
padding-bottom: 20px;
}

.e-teaser__headline {
font-size: 30px;
}

.e-teaser__headline--highlight {
color: red;
}

.e-teaser__content {
padding: 20px 0;
}

.e-teaser--active .e-teaser__content {
color: red;
}

Verschachtelungen sind ein weiterer Punkt, den man so wenig wie möglich nutzen sollte, um seinen Code übersichtlich und einfach zu handhaben machen.

So sollte man z.B. bei einer Navigation anstatt:

.e-nav {
  ul {
li {
a {
      }
      ul {
li {
a {

}
}
}
}
}
}

lieber:

.e-nav {
  ul {
  }
  li {
  }

a {
  }
  ul ul {

li {
    }
    a {

}
  }
}

schreiben. Somit hält man die Hierarchie schön flach, und kann die einzelnen Elemente einfacher modifizieren.

Mit der Verschachtelung von Selektoren erhöht sich die Spezifität der jeweilig gesetzten Eigenschaften. Das verhindert das Überschreiben von Eigenschaften durch weniger spezifische Klassen. Daher sollte man eine Verschachtelung möglichst vermeiden.

Beispiel: Wir erstellen ein Wordpress-Template, bei dem man zwischen verschiedenen vorgegebenen Farb-Sets wählen kann.

Dafür erstellen wir ein Stylesheet (style.scss), welches alle Abstände, Positionen und ein Basic-Farbset enthält, und eines (colors.scss), welches sich vollkommen auf Farben konzentriert.

Würden wir uns nicht an flache Hierarchien handeln, müssten wir, nur um die Linkfarben der Navigation zu überschreiben, uns durch jedes Element hangeln:

.e-nav {
ul {
li {
a {
color: blue
}
      ul {
li {
a {
color: blue
}
}
}
}
}
}

Anstatt einfach

.e-nav {
a {
color: blue
}
ul ul {
a {
color: blue
}
}
}

schreiben zu können.


Alternativen zu BEM

Neben BEM gibt es unter anderem noch folgende Konventionen: OOCSS, SMACSS, SUITCSS und Atomic.

Es gibt eine Atomic-Konvention? Warum verwenden wir nicht die?

In der Tat würde der Grundgedanke dieser Konvention unserem Atomic-Design-Ansatz absolut entsprechen. Der Grund warum ich sie dennoch nicht verwende, ist die Lesbarkeit.

Eine Atomic-CSS Komponente könnte wie folgt aussehen:

<div class="Bfc M-10">
<a href="/" class="Fl-start Mend-10">
<img src="image.jpg" alt="img" />
</a>
<div class="Bfc Fz-s">
Metadaten
</div>
</div>

Rein ohne Zusammenhang wissen wir hier nicht, um was für ein Element es sich hier handelt, oder was die einzelnen Klassen machen.

Es ist wichtig, dass unser Code sowohl im HTML als auch im CSS nachvollziehbar ist.


CSS for runaways

Wer sich noch weiter mit der Optimierung von CSS-Code in Hinsicht auf Lesbarkeit beschäftigen möchte, dem empfehle ich wärmstens, sich mit folgenden Guidelines zu beschäftigen:

Hier wird sehr übersichtlich auf verschiedene Aspekte der Formatierung, Kommentierung und Attributreihenfolge eingegangen.


Zusammenfassung

Ich habe nun schon öfter betont, dass es wichtig ist, Code nachvollziehbar und wiederverwendbar zu schreiben. Mit BEM und Atomic Design erreichen wir beides.

Next

Im nächsten Teil verbinden wir dann Atomic CSS und BEM in einem praktischen Beispiel.