Als Frontend-Entwickler mit fast 15 Jahren Erfahrung habe ich die Entwicklung der Webentwicklung aus erster Hand miterlebt. Für mich ist es ein langer Weg von den Tagen des Hochladens geänderter Dateien per FTP (ja, GitHub wurde vor 15 Jahren gestartet, aber ich habe es erst 2011 entdeckt) bis zur modernen Ära responsiver Schnittstellen, UI-Bibliotheken und direkt daraus generierten Websites Figma.
Dennoch stoße ich immer noch auf Projekte, die verschachtelte Stile verwenden, wie zum Beispiel:
.some-class ul li div a { /* some style */ }
oder,
#nav .nav-link svg { /* some style */ }
Es mag schockierend erscheinen, aber solche Codierungspraktiken durchdringen alles, von schnell wachsenden Multimillionen-Dollar-Projekten bis hin zu bescheidenen Startups.
Lassen Sie uns untersuchen, warum dieser Ansatz Probleme bereiten kann.
Tief verschachtelte Stile führen oft zu Stilkonflikten, insbesondere wenn Sie ein großes Projekt haben. Als kaskadierendes Stylesheet wird CSS kaskadiert und je nach Spezifität auf Elemente angewendet. Tief verschachtelte Stile können aufgrund ihrer Spezifität andere Stile unbeabsichtigt überschreiben.
Betrachten Sie dieses Beispiel:
.some-class ul li div a { color: red; } ... .some-class a { color: blue; }
Sie könnten erwarten, dass alle Links in .some-class
blau sind. Aufgrund der größeren Spezifität der ersten Regel ist jedoch jeder Link, der in einem ul > li > div
verschachtelt ist, rot und nicht blau. Dies kann zu unerwarteten visuellen Inkonsistenzen und viel Zeitverschwendung beim Debuggen führen.
Das Verständnis des Konzepts der Spezifität (oder des „Gewichts“ von Stilen) in CSS ist entscheidend, um zu verstehen, warum tiefe Verschachtelung problematisch sein kann. Die Spezifität bestimmt, welche CSS-Regel gilt, wenn mehrere Regeln um ein einzelnes Element konkurrieren. Sie wird basierend auf der Art und Anzahl der Selektoren berechnet.
Die Spezifität wird basierend auf einem Gewichtungssystem mit vier Kategorien berechnet:
Beachten Sie hier die Regel:
body #content .data img:hover { /* some style */ }
Die Spezifität beträgt 0 1 2 2 . Das sind eine ID ( #content ), zwei Klassen ( .data und :hover ) und zwei Elemente ( body und img ).
Betrachten Sie nun die Regel:
#nav .nav-link svg { /* some style */ }
Die Spezifität beträgt hier 0 1 1 1 . Das ist eine ID ( #nav
), eine Klasse ( .nav-link
) und ein Element ( svg
).
Spezifität basiert nicht auf einem „Übertrag“-System wie herkömmliche Dezimalzahlen. Beispielsweise ist ein Selektor mit einer Spezifität von 0 1 0 11 nicht gleich einer Spezifität von 0 1 1 1, obwohl in einem Dezimalsystem 11 und 1+1 gleichwertig wären.
Schließlich haben der universelle Selektor ( *
), die Kombinatoren ( +
, >
, ~
, ' ') und die Negationspseudoklasse ( :not()
) keinen Einfluss auf die Spezifität. Innerhalb des :not()
Arguments werden die Selektoren jedoch wie gewohnt gezählt.
Für visuelle Lerner empfehle ich dieses Video über CSS-Spezifität.
Wenn Sie die CSS-Spezifität und deren Berechnung verstehen, können Sie besseres, vorhersehbareres CSS schreiben und Probleme beheben, wenn Stile nicht wie erwartet angewendet werden.
!important
Regel und Besonderheit Manchmal greifen Entwickler auf die !important
Regel zurück, wenn sie Schwierigkeiten mit CSS-Spezifitätskonflikten haben. Diese Regel macht eine CSS-Eigenschaft äußerst spezifisch, was bedeutet, dass sie fast jede andere Deklaration überschreibt.
Zum Beispiel:
#nav .nav-link svg { color: blue; } .nav-link svg { color: red !important; }
Obwohl die erste Regel aufgrund des ID-Selektors eine höhere Spezifität aufweist, wäre die Farbe des svg
aufgrund des !important
in der zweiten Regel rot.
Auch wenn !important
eine schnelle Lösung sein kann, wenn Sie mit Spezifitätsproblemen zu kämpfen haben, ist es nicht empfehlenswert, es ausgiebig zu verwenden. Übermäßiger Gebrauch kann die Wartbarkeit, Vorhersagbarkeit und Leistung beeinträchtigen. In größeren Projekten deutet die übermäßige Verwendung von !important
häufig auf Schwierigkeiten bei der Verwaltung der CSS-Spezifität hin. Anstatt auf !important
zurückzugreifen, ist es oft besser, Zeit in die Umgestaltung Ihres CSS zu investieren und die Verwendung übermäßig spezifischer Selektoren zu reduzieren.
Sie können Ihr Produkt jetzt überprüfen 🙂. Ich habe meines überprüft:
Während !important
eine verlockende schnelle Lösung sein könnte; Es ist, als würde man mit einem Vorschlaghammer eine Nuss knacken. Ein wartbarerer Ansatz besteht darin, Ihre Selektoren so einfach und flach wie möglich zu halten, damit Ihr CSS in Zukunft leichter zu verstehen, zu verwalten und zu erweitern ist. Und denken Sie daran: Der beste Weg, einen !important
Krieg zu gewinnen, besteht darin, ihn gar nicht erst zu beginnen.
Ein weiteres Problem bei tief verschachtelten Stilen ist die Auswirkung auf die Leistung beim Browser-Rendering. Wenn ein Browser Stile auf ein Element anwendet, durchläuft er das DOM von rechts nach links, beginnend mit der Tastenauswahl (in unseren Beispielen a
und svg
) und durchläuft die Vorfahren, bis er eine Übereinstimmung findet oder die Spitze erreicht. Je verschachtelter der Stil ist, desto länger dauert dieser Durchlauf, was möglicherweise die Leistung beeinträchtigt und die Seitenladezeiten bei großen Projekten verlangsamt.
Wenn Sie eine CSS-Regel angeben, wie zum Beispiel:
.some-class ul li a { /* some style */ }
Sie können sich diese Regel vorstellen, beginnend am unteren Ende des Baums (vom a
Tag) und sich durch den Baum nach oben arbeitend (über li
, ul
und .some-class
).
Der Browser sucht zunächst nach allen (ich meine ALLE) a
Elementen und prüft dann, ob sich diese a
Tags in li
Elementen befinden. Danach wird geprüft, ob sich diese li
Elemente in ul
befinden. Und schließlich wird geprüft, ob sich diese ul
in einem Element mit der Klasse .some-class
befinden.
Dies ist die Art und Weise, wie Browser CSS-Selektoren lesen und der Grund, warum komplexe Selektoren zu einer langsameren Seitenwiedergabe führen können. Der Browser muss für jedes Element mehrere Prüfungen durchführen, um festzustellen, ob es der angegebenen Regel entspricht. Je tiefer die Regel, desto mehr Prüfungen muss der Browser durchführen, was sich auf die Leistung auswirken kann.
Mit CSS-Modulen können Sie CSS in einzelnen Modulen schreiben, die lokal auf die Komponente beschränkt sind, an der Sie arbeiten. Das bedeutet, dass Stile in einem CSS-Modul nur auf dieses spezifische Modul anwendbar sind und nicht nach außen dringen oder andere Elemente auf der Seite beeinträchtigen.
Lassen Sie uns untersuchen, wie CSS-Module gehashte Klassennamen verwenden, um die Stilkapselung sicherzustellen. Wenn Sie CSS-Module verwenden, werden die Klassennamen, die Sie in Ihrer CSS-Datei definieren, zur Kompilierungszeit gehasht. Dieser Hash erstellt einen eindeutigen Klassennamen, der Ihrer Komponente entspricht. Schauen wir uns ein Beispiel an:
Angenommen, Sie haben ein CSS-Modul wie folgt definiert:
/* Button.module.css */ .button { color: white; background-color: blue; }
Und Sie verwenden es in Ihrer Komponente wie folgt (ich bevorzuge den Import des Styles-Objekts als s
statt als styles
– ein kurzer Tipp, der Tippzeit spart und die Codierungseffizienz steigert):
import React from 'react'; import s from './Button.module.css'; const Button = () => { return ( <button className={s.button}>Click me</button> ); }; export default Button;
Wenn Ihre Anwendung kompiliert ist, könnte Ihr gerenderter HTML-Code etwa so aussehen:
<button class="Button_button__3FQ9Z">Click me</button>
In diesem Fall ist Button_button__3FQ9Z
der gehashte Klassenname, der von Ihrem CSS-Modul generiert wurde. Beachten Sie, dass die genaue Struktur und Länge des Hashs je nach Projektkonfiguration variieren kann.
Dieser eindeutige Klassenname stellt sicher, dass die Stile, die Sie in Button.module.css
definiert haben, nur für diese Schaltfläche gelten und keine Auswirkungen auf andere Elemente in Ihrer Anwendung haben. Es stellt außerdem sicher, dass keine anderen Stile diese Schaltfläche beeinflussen können, es sei denn, sie zielen explizit auf den gehashten Klassennamen ab. Diese Kapselung von Stilen ist einer der Hauptvorteile von CSS-Modulen.
Eine weitere beliebte Möglichkeit, mit CSS umzugehen, ist die Verwendung von CSS-in-JS-Bibliotheken wie styled-components oder emotions . Mit diesen Bibliotheken können Sie Ihr CSS direkt in Ihrem JavaScript schreiben, was mehrere Vorteile hat:
Hier ist ein Beispiel dafür, wie Sie styled-components in einer React-Anwendung verwenden können:
import React from 'react'; import styled from 'styled-components'; const Button = styled.button` color: white; background-color: ${(props) => props.primary ? 'blue' : 'gray'}; `; const App = () => { return ( <div> <Button primary>Primary Button</Button> <Button>Secondary Button</Button> </div> ); }; export default App;
In diesem Beispiel verfügt die Button
Komponente über dynamische Stile, die sich je nach ihrer primary
Requisite ändern.
Wenn Sie nicht mit einem JavaScript-Framework arbeiten, das CSS-Module oder ähnliches unterstützt, können Sie Ihr CSS dennoch effektiv verwalten, indem Sie Benennungsmethoden wie BEM (Block, Element, Modifier) verwenden.
BEM steht für „Block Element Modifier“ und ist eine Methode, die Ihnen hilft, wiederverwendbare Komponenten und Code-Sharing in CSS zu erstellen. So können Sie Ihr CSS mit BEM strukturieren:
/* Block */ .top-menu { } /* Element */ .top-menu__item { } /* Modifier */ .top-menu__item_active { }
In BEM ist der „Block“ die eigenständige Einheit, die für sich genommen eine Bedeutung hat, das „Element“ ist ein Teil des Blocks, der keine eigenständige Bedeutung hat und semantisch an seinen Block gebunden ist, und der „Modifikator“ ist ein aktiviertes Flag ein Block oder Element, das zum Ändern des Aussehens oder Verhaltens verwendet wird.
Die Verwendung einer konsistenten Methodik wie BEM kann Ihr CSS leichter verständlich und pflegeleicht machen, insbesondere bei größeren Projekten.
Es gibt verschiedene Möglichkeiten, CSS in größeren Projekten zu verwalten, von CSS-Modulen und CSS-in-JS-Bibliotheken bis hin zu Benennungsmethoden wie BEM. Der Schlüssel liegt darin, einen Ansatz zu finden, der gut zu Ihrem Team und Projekt passt, und ihn konsequent anzuwenden. Denken Sie daran, dass es beim Schreiben von CSS genauso darum geht, Code zu schreiben, der effizient und performant ist, wie auch darum, Code zu schreiben, der verständlich und wartbar ist.
Viel Spaß beim Codieren!