Was sind CSS-Module und warum brauchen wir sie?

Avatar of Robin Rendle
Robin Rendle am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich war in letzter Zeit von CSS-Modulen fasziniert. Wenn Sie noch nichts davon gehört haben, ist dieser Beitrag für Sie. Wir werden uns das Projekt und seine Ziele und Absichten ansehen. Wenn Sie neugierig sind, bleiben Sie dran, denn der nächste Beitrag wird sich damit befassen, wie man mit dieser Idee anfängt. Wenn Sie Ihre Nutzung implementieren oder verbessern möchten, wird Teil 3 die Verwendung in einer React-Umgebung behandeln.

Artikelserie

  1. Was sind CSS-Module und warum brauchen wir sie? (Hier sind Sie!)
  2. Getting Started with CSS Modules
  3. React + CSS-Module = 😍

Was sind CSS-Module?

Laut dem Repo sind CSS-Module

CSS-Dateien, in denen alle Klassennamen und Animationsnamen standardmäßig lokal verkapselt sind.

CSS-Module sind also keine offizielle Spezifikation oder Implementierung im Browser, sondern vielmehr ein Prozess in einem Build-Schritt (mit Hilfe von Webpack oder Browserify), der Klassennamen und Selektoren so verändert, dass sie verkapselt sind (d. h. so etwas wie namensraumbezogen sind).

Wie sieht das aus und warum sollte man es tun? Dazu kommen wir gleich. Erinnern Sie sich zunächst, wie HTML und CSS normalerweise funktionieren. Eine Klasse wird in HTML angewendet

<h1 class="title">An example heading</h1>

Und diese Klasse wird in CSS gestylt

.title {
  background-color: red;
}

Solange dieses CSS auf das HTML-Dokument angewendet wird, wäre der Hintergrund dieses <h1> rot. Wir müssen das CSS oder das HTML nicht verarbeiten. Der Browser versteht beide Dateiformate.

CSS-Module verfolgen einen anderen Ansatz. Anstatt reines HTML zu schreiben, müssen wir unseren gesamten Markup-Code in einer JavaScript-Datei schreiben, z. B. index.js. Hier ist ein Beispiel dafür, wie das funktionieren könnte (ein realistischeres Beispiel sehen wir uns später an)

import styles from "./styles.css";

element.innerHTML = 
  `<h1 class="${styles.title}">
     An example heading
   </h1>`;

Während unseres Build-Schritts würde der Compiler die importierte styles.css-Datei durchsuchen, dann das geschriebene JavaScript durchgehen und die Klasse .title über styles.title zugänglich machen. Unser Build-Schritt würde dann beides in neue, separate HTML- und CSS-Dateien verarbeiten, wobei eine neue Zeichenkette sowohl die HTML-Klasse als auch die CSS-Selektorklasse ersetzt.

Unser generiertes HTML könnte so aussehen

<h1 class="_styles__title_309571057">
  An example heading
</h1>

Unser generiertes CSS könnte so aussehen

._styles__title_309571057 {
  background-color: red;
}

Das Klassenattribut und der Selektor .title sind vollständig verschwunden und wurden durch diese völlig neue Zeichenkette ersetzt; unser ursprüngliches CSS wird überhaupt nicht an den Browser ausgeliefert.

Wie Kitty Giraudel in ihrem Tutorial zu diesem Thema sagte

[die Klassen] sind dynamisch generiert, einzigartig und den richtigen Stilen zugeordnet.

Das ist es, was mit "Styles sind verkapselt" gemeint ist. Sie sind auf bestimmte Vorlagen beschränkt. Wenn wir eine buttons.css-Datei hätten, würden wir sie nur in eine buttons.js-Vorlage importieren, und eine Klasse .btn darin wäre für eine andere Vorlage (z. B. forms.js) unzugänglich, es sei denn, wir würden sie dort explizit importieren.

Warum sollten wir das CSS und HTML verändern, um das zu erreichen? Warum zum Teufel sollten wir auf diese Weise arbeiten?

Warum sollten wir CSS-Module verwenden?

Mit CSS-Modulen ist garantiert, dass alle Stile für eine einzelne Komponente

  1. An einem Ort liegen
  2. Nur auf diese Komponente angewendet werden und nichts anderes

Außerdem kann jede Komponente eine echte Abhängigkeit haben, wie z.B.

import buttons from "./buttons.css";
import padding from "./padding.css";

element.innerHTML = `<div class="${buttons.red} ${padding.large}">`;

Dieser Ansatz wurde entwickelt, um das Problem des globalen Geltungsbereichs in CSS zu lösen.

Waren Sie jemals versucht, aus Zeit- oder Ressourcenmangel einfach so schnell wie möglich CSS zu schreiben, ohne darüber nachzudenken, was Sie noch beeinflussen könnten?

Haben Sie jemals zufällige Teile und Junk am Ende eines Stylesheets angehängt, in der Absicht, es später zu organisieren, aber es nie getan?

Sind Sie jemals auf Stile gestoßen, bei denen Sie nicht ganz sicher waren, was sie tun oder ob sie überhaupt verwendet werden?

Haben Sie sich jemals gefragt, ob Sie einige Stile entfernen könnten, ohne etwas zu beschädigen? Sich gefragt, ob die Stile für sich allein standen oder von anderen Dingen abhingen? Oder Stile anderswo überschrieben?

Das sind Fragen, die zu großen Kopfschmerzen, aufgeblähten Projektfristen und traurigen, sehnsüchtigen Blicken aus dem Fenster führen können.

Mit CSS-Modulen und dem Konzept des **standardmäßigen lokalen Geltungsbereichs** wird dieses Problem vermieden. Sie sind immer gezwungen, über die Konsequenzen nachzudenken, während Sie Stile schreiben.

Wenn Sie beispielsweise random-gross-class in HTML verwenden, ohne es als CSS-Module-Stilklasse anzuwenden, wird der Stil nicht angewendet, da der CSS-Selektor in ._style_random-gross-class_0038089 umgewandelt wird.

Das Schlüsselwort composes

Nehmen wir an, wir haben ein Modul namens type.css für unsere Textstile. In dieser Datei hätten wir Folgendes

.serif-font {
  font-family: Georgia, serif;
}

.display {
  composes: serif-font;
  font-size: 30px;
  line-height: 35px;
}

Wir würden eine dieser Klassen in unserer Vorlage so deklarieren

import type from "./type.css";

element.innerHTML = 
  `<h1 class="${type.display}">
    This is a heading
  </h1>`;

Dies würde zu folgendem Markup führen

<h1 class="_type__display_0980340 _type__serif_404840">
  Heading title
</h1>

Beide Klassen wurden durch die Verwendung des Schlüsselworts composes an das Element gebunden und vermeiden so einige der Probleme ähnlicher Lösungen wie Sass' @extend.

Wir können sogar von einer bestimmten Klasse in einer separaten CSS-Datei kompilieren

.element {
  composes: dark-red from "./colors.css";
  font-size: 30px;
  line-height: 1.2;
}

BEM nicht erforderlich

Wir müssen BEM nicht verwenden, wenn wir ein CSS-Modul erstellen. Das hat zwei Gründe

  1. Einfache Analyse – Code wie type.display ist für Entwickler genauso lesbar wie das BEM-mäßige .font-size__serif--large. Wahrscheinlich sogar leichter zu erfassen, wenn die BEM-Selektoren lang werden.
  2. Lokaler Geltungsbereich – Sagen wir, wir haben eine Klasse wie .big in einem Modul, die die font-size ändert. In einem anderen verwenden wir dieselbe Klasse .big, die padding und font-size in einer anderen Menge erhöht. Das spielt einfach keine Rolle! Sie werden nicht kollidieren, da die Stile sehr bewusst verkapselt sind. Selbst wenn ein Modul beide Stylesheets importiert, hat es einen benutzerdefinierten Namen, den unser Build-Prozess speziell für diese Klasse erstellt. Mit anderen Worten, **Spezifitätsprobleme verschwinden mit CSS-Modulen.**

Cool, oder?

Dies sind nur einige der Vorteile des Schreibens von CSS-Modulen.

Wenn Sie mehr erfahren möchten, hat Glen Madden ausführlich über einige der anderen Vorteile dieses Ansatzes geschrieben.

Der nächste Artikel in dieser Reihe befasst sich damit, wie man ein Projekt mit Webpack und CSS-Modulen zum Laufen bringt. Wir werden die neuesten ES2015-Funktionen verwenden, um dies zu tun, und uns einige Beispielcodes ansehen, die uns durch den Prozess führen.

Weitere Lektüre

Artikelserie

  1. Was sind CSS-Module und warum brauchen wir sie? (Hier sind Sie!)
  2. Getting Started with CSS Modules
  3. React + CSS-Module = 😍