Heim >Web-Frontend >CSS-Tutorial >Zähmung der Kaskade mit BEM und modernen CSS -Selektoren

Zähmung der Kaskade mit BEM und modernen CSS -Selektoren

Jennifer Aniston
Jennifer AnistonOriginal
2025-03-10 11:59:17340Durchsuche

Taming the Cascade With BEM and Modern CSS Selectors

Bem. Wie fast alle Technologien in der Front-End-Entwicklung kann das Schreiben von CSS im BEM-Format eine Polarisation verursachen. Aber in meinem sozialen Twitter -Kreis ist es mindestens eine der beliebtesten CSS -Methoden.

Ich persönlich denke Bem ist gut und ich denke, Sie sollten es verwenden. Ich kann aber auch verstehen, warum Sie es möglicherweise nicht verwenden.

Unabhängig von Ihrer Meinung zu BEM bietet es einige Vorteile, der größte Vorteil ist, dass es dazu beiträgt, spezifische Konflikte in der CSS -Kaskade zu vermeiden. Dies liegt daran, dass jeder im BEM -Format geschriebene Selektor bei ordnungsgemäß die gleiche Spezifitätsbewertung (0,1,0) haben sollte. Im Laufe der Jahre habe ich CSS für viele große Websites entworfen (denken Sie an Regierung, Universitäten und Banken). Diese großen Projekte haben mich entdeckt, wo Bem wirklich glänzt. Das Schreiben von CSS macht mehr Spaß, wenn Sie sicher sind, dass der Stil, den Sie schreiben oder bearbeiten, andere Teile der Website nicht beeinflusst.

In einigen Fällen wird das Hinzufügen von Spezifität als völlig akzeptabel angesehen. Zum Beispiel:

und :hover Pseudoklasse. Ihre Spezifitätswerte betragen 0,2,0. Das andere sind Pseudoelemente-zum Beispiel :focus und ::before-ihre Spezifitätswerte beträgt 0,1,1. Nehmen wir jedoch im Rest dieses Artikels an, dass wir keine andere spezifische Ausbreitung erwarten. ? ::after

Aber ich möchte dich nicht wirklich verkaufen. Stattdessen möchte ich darüber sprechen, wie wir es in Verbindung mit modernen CSS -Selektoren (z. B.

, :is(), :has() usw.) verwenden, um eine stärkere Kaskadenkontrolle zu erhalten. :where()

Was ist ein moderner CSS -Selektor?

Die Spezifikation der CSS -Selektorstufe 4 bietet uns einige leistungsstarke und relativ neue Möglichkeiten zur Auswahl von Elementen. Einige meiner Favoriten umfassen

, :is() und :where(), die alle von allen modernen Browsern unterstützt werden und jetzt in fast jedem Projekt sicher verwendet werden. :not()

und :is() sind im Grunde gleich, außer dass sie unterschiedliche Auswirkungen auf die Spezifität haben. Insbesondere beträgt der Spezifitätswert von :where() immer 0,0,0. Ja, auch :where() ist nicht spezifisch. Gleichzeitig ist die Spezifität von :where(button#widget.some-class) die Spezifität des spezifischsten Elements in seiner Parameterliste. Daher haben wir bereits den Unterschied in der Kaskadenverlauf zwischen zwei modernen Selektoren, die verwendet werden können. :is()

Die leistungsstarke

relationale Pseudoklasse gewinnt auch schnell Browserunterstützung (meiner Meinung nach ist dies das größte neue Merkmal von CSS seit dem Netz). Zum Zeitpunkt des Schreibens ist die Browser -Unterstützung für :has() jedoch nicht gut genug, um in Produktionsumgebungen verwendet zu werden. :has()

Lassen Sie mich meinem Bem eine Pseudoklasse hinzufügen ...

<code>/* ❌ 特异性分数:0,2,0 */
.something:not(.something--special) {
  /* 所有 something 的样式,除了特殊的 something */
}</code>

Oh nein! Hast du diese spezifische Punktzahl gesehen? Denken Sie daran, dass wir mit BEM idealerweise erwarten, dass unsere Selektoren spezifische Punktzahlen von 0,1,0 haben. Warum 0,2,0 ist nicht gut? Betrachten Sie ein ähnliches Erweiterungsbeispiel:

<code>.something:not(a) {
  color: red;
}
.something--special {
  color: blue;
}</code>

Auch wenn der zweite Selektor schließlich in der Quellcodesequenz erscheint, wird die höhere Spezifität des ersten Selektors (0,1,1) gewinnen, und die Farbe des .something--special -Elements wird auf rot eingestellt. Angenommen, Ihr BEM ist korrekt geschrieben und das ausgewählte Element wendet sowohl die .something Basisklasse als auch die .something--special -Modifikatorklasse in HTML an.

Wenn diese Pseudoklassen nicht ordnungsgemäß verwendet werden, können sie die Kaskade auf unerwartete Weise beeinflussen. Es sind diese Inkonsistenzen, die später Probleme verursachen können, insbesondere in größeren und komplexeren Codebasen.

Oh. Also, was ist jetzt zu tun?

Erinnerst du dich, was ich gerade gesagt habe :where() und seine Spezifität ist Null? Wir können dies ausnutzen:

<code>/* ✅ 特异性分数:0,1,0 */
.something:where(:not(.something--special)) {
  /* 等 */
}</code>

Der erste Teil dieses Selektors (.something) erhält seinen üblichen Spezifitätswert 0,1,0. Aber die Spezifität von :where() - und alles darin - ist 0 und erhöht die Selektorspezifität nicht weiter.

: Wo () erlaubt es uns,

zu nisten

Diejenigen, die sich nicht so sehr für Spezifität interessieren, wie ich es tue (und um fair zu sein, wahrscheinlich viele Menschen) haben es gut gemacht, zu nisten. Bei einiger zufälliger Tastatur -Tipps erhalten wir möglicherweise CSS wie diesen (beachten Sie, dass ich SASS zum Einfachheit halber verwende):

<code>.card { ... }

.card--featured {
  /* 等 */  
  .card__title { ... }
  .card__title { ... }
}

.card__title { ... }
.card__img { ... }</code>

In diesem Beispiel haben wir eine .card -Komponente. Wenn es sich um eine "vorgestellte" Karte (unter Verwendung der .card--featured -Klasse) handelt, müssen der Titel und das Bild der Karte unterschiedliche Stile sein. Wie wir jetzt wissen, stehen die durch den obigen Code verursachten Spezifitätswerte mit dem Rest unseres Systems nicht überein. Ein hartnäckiger spezifischer Fanatiker könnte dies tun:

Es ist nicht schlecht, oder? Ehrlich gesagt ist dies ein hübsches CSS.
<code>.card { ... }
.card--featured { ... }
.card__title { ... }
.card__title--featured { ... }
.card__img { ... }
.card__img--featured { ... }</code>

HTML hat jedoch auch seine Nachteile. Erfahrene BEM -Autoren können schmerzlich bewusst sein, dass eine komplexe Vorlagelogik erforderlich ist, um Modifikatorklassen auf mehrere Elemente anzuwenden. In diesem Beispiel muss die HTML-Vorlage die

-Modifikatorklasse zu drei Elementen (

, --featured und .card) bedingt hinzufügen, aber es kann möglicherweise mehr in realen Beispielen sein. Es gibt viele wenn auch Aussagen. .card__title .card__img

Selektoren können uns helfen, weniger Vorlagenlogik - und weniger BEM -Klassen - zu schreiben, was die Spezifitätsstufe erhöht.

:where()

Folgendes ist der gleiche Inhalt in SASS (beachten Sie die Nachverfolgung gegen):
<code>.card { ... }
.card--featured { ... }

.card__title { ... }
:where(.card--featured) .card__title { ... }

.card__img { ... }
:where(.card--featured) .card__img { ... }</code>

ob Sie diese Methode auswählen sollten, anstatt die Modifikator -Klasse auf verschiedene untergeordnete Elemente anzuwenden, hängt von der persönlichen Präferenz ab. Aber zumindest
<code>.card { ... }
.card--featured { ... }
.card__title { 
  /* 等 */ 
  :where(.card--featured) & { ... }
}
.card__img { 
  /* 等 */ 
  :where(.card--featured) & { ... }
}</code>
jetzt haben wir die Wahl!

Was soll ich tun, wenn ich kein BEM HTML habe?

Wir leben in einer unvollkommenen Welt. Manchmal müssen Sie sich mit HTML befassen, die über Ihre Kontrolle hinausgehen. Injizieren Sie beispielsweise ein Drittanbieter-Skript, das Sie zum Style HTML benötigen. Diese Tags werden normalerweise nicht mit Namen der BEM -Klasse geschrieben, und in einigen Fällen verwenden diese Stile überhaupt keine Klassen, sondern IDs!

In ähnlicher Weise kann :where() uns auch helfen, dieses Problem zu lösen. Diese Lösung ist etwas ungeschickt, da wir uns auf eine Klasse im DOM -Baum beziehen müssen, von dem wir wissen, dass es existiert.

<code>/* ❌ 特异性分数:0,2,0 */
.something:not(.something--special) {
  /* 所有 something 的样式,除了特殊的 something */
}</code>

zitieren das übergeordnete Element fühlt sich ein bisschen riskant und restriktiv an. Was ist, wenn sich die Elternklasse ändert oder aus irgendeinem Grund nicht existiert? Eine bessere (aber vielleicht ebenso ungeschickte) Lösung besteht darin, stattdessen :is() zu verwenden. Denken Sie daran, dass die Spezifität von :is() gleich dem spezifischsten Selektor in seiner Auswahlliste ist.

damit können wir :is() verwenden, um eine Klasse zu verweisen, die wir kennen (oder hoffen!), Anstatt :where() wie im obigen Beispiel zu verwenden.

<code>.something:not(a) {
  color: red;
}
.something--special {
  color: blue;
}</code>

Das immer bestehende body hilft uns, das #widget -Element auszuwählen, und das Vorhandensein der :is() -Klasse im selben .dummy-class macht den body -Auskörper die gleiche Spezifitätsbewertung (0,1,0) wie die Klasse… und verwendet :where(), um sicherzustellen, dass die Selektor nicht spezifischer als diese ist.

Das ist es!

So nutzen wir die modernen spezifischen Verwaltungsfähigkeiten der :is() und :where() Pseudoklasse sowie die spezifischen Konfliktpräventionsfähigkeiten beim Schreiben von CSS im BEM-Format. In naher Zukunft, sobald :has() von Firefox unterstützt wird (es wird derzeit zum Zeitpunkt des Schreibens hinter dem Logo unterstützt), möchten wir es vielleicht mit :where() kombinieren, um seine Spezifität rückgängig zu machen.

Egal, ob Sie mit BEM voll benennen oder nicht, ich hoffe, wir können zustimmen, dass die Selektorspezifität eine gute Sache ist!

Das obige ist der detaillierte Inhalt vonZähmung der Kaskade mit BEM und modernen CSS -Selektoren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn