CSS-Selektoren

Avatar of Geoff Graham
Geoff Graham am

Ein vollständiger Leitfaden über alle verschiedenen Methoden, die uns zur Auswahl von Elementen in CSS zur Verfügung stehen, und wie man sie zur Anwendung von Styles verwendet.

Präsentiert von DigitalOcean

DigitalOcean bietet die Cloud-Computing-Dienste, die Sie benötigen, um Ihr Wachstum in jeder Phase zu unterstützen. Starten Sie mit einem kostenlosen Guthaben von 200 $!

Überblick

CSS ist in vielen Bereichen sehr gut, aber es ist wirklich, wirklich gut in zwei speziellen Dingen: Elemente auswählen und sie gestalten. Das ist der raison d’être für CSS und warum es eine Kern-Websprache ist. In diesem Leitfaden werden wir die verschiedenen Möglichkeiten zur Auswahl von Elementen behandeln – denn die Stile, die wir schreiben, sind so gut wie nutzlos, wenn wir nicht die Fähigkeit haben, auszuwählen, welche Elemente wir auf sie anwenden.

Die Quelle der Wahrheit für CSS-Selektoren ist in der Selectors Module Level 4-Spezifikation dokumentiert. Mit einer Ausnahme (zu der wir noch kommen werden) werden alle hier behandelten Selektoren von Browsern durchgängig gut unterstützt, und die meisten sicherlich von allen modernen Browsern.

Zusätzlich zu Selektoren befasst sich dieser Leitfaden auch mit CSS-Kombinatoren. Wenn Selektoren identifizieren, was wir auswählen, könnten Sie Kombinatoren als wie die Stile angewendet werden betrachten. Kombinatoren sind wie zusätzliche Anweisungen, die wir CSS geben, um ein ganz bestimmtes Element auf der Seite auszuwählen, nicht völlig unähnlich der Art und Weise, wie wir Filter in Suchmaschinen verwenden können, um das exakte gewünschte Ergebnis zu finden.

Schnellübersicht

Gängige Selektoren

/* Universal */
* {
  box-sizing: border-box;
}

/* Type or Tag */
p {
  margin-block: 1.5rem;
}

/* Classname */
.class {
  text-decoration: underline;
}

/* ID */
#id {
  font-family: monospace;
}

/* Relational */
li:has(a) {
  display: flex;
}

Gängige Kombinatoren

/* Descendant */
header h1 {
  /* Selects all Heading 1 elements in a Header element. */
}

/* Child */
header > h1 {
  /* Selects all Heading 1 elements that are children of Header elements. */
}

/* General sibling */
h1 ~ p {
  /* Selects a Paragraph as long as it follows a Heading 1. */
}

/* Adjacent sibling */
h1 + p {
  /* Selects a Paragraph if it immediately follows a Heading 1 */
}

/* Chained */
h1, p { 
  /* Selects both elements. */
}

Allgemeine Selektoren

Wenn wir über CSS-Selektoren sprechen, sprechen wir über den ersten Teil einer CSS-Regel

/* CSS Ruleset */
selector {
  /* Style rule */
  property: value;
}

Sehen Sie diesen selector? Das kann so einfach sein wie das HTML-Tag, das wir auswählen wollen. Zum Beispiel wählen wir alle <article>-Elemente auf einer bestimmten Seite aus.

/* Select all <article> elements... */
article {
  /* ... and apply this background-color on them */
  background-color: hsl(25 100% 50%);
}

Das ist der allgemeine Prozess des Auswählens von Elementen, um ihnen Stile zuzuweisen. Das Auswählen eines Elements anhand seines HTML-Tags ist lediglich ein Selektortyp von mehreren. Sehen wir uns im folgenden Abschnitt an, welche das sind.

Element-Selektoren

Element-Selektoren sind genau die Art von Selektor, die wir in diesem letzten Beispiel betrachtet haben: Wählen Sie das HTML-Tag des Elements aus und beginnen Sie mit dem Styling!

Das ist alles schön und gut, aber bedenken Sie Folgendes: Möchten Sie wirklich alle <article>-Elemente auf der Seite auswählen? Das tun wir, wenn wir ein Element anhand seines Tags auswählen – alle HTML-Elemente, die diesem Tag entsprechen, erhalten die Stile. Die folgende Demo wählt alle <article>-Elemente auf der Seite aus und wendet dann einen weißen (#fff) Hintergrund darauf an. Beachten Sie, wie alle drei Artikel den weißen Hintergrund erhalten, obwohl wir nur einen Selektor geschrieben haben.

Ich habe versucht, den relevanten Code für diese und andere Demos im CSS-Tab oben bereitzustellen. Alles in einem @layer kann ignoriert werden. Und wenn Sie neu bei @layer sind, können Sie alles darüber in unserem CSS Cascade Layers Guide erfahren.

Aber vielleicht möchten wir, dass das erste Element einen anderen Hintergrund hat – vielleicht ist es ein hervorgehobener Inhalt und wir müssen es von den anderen Artikeln abheben. Dazu müssen wir spezifischer bei der Art des Selektors sein, den wir verwenden, um die Stile anzuwenden.

Konzentrieren wir uns nun auf andere Selektortypen, die es uns ermöglichen, spezifischer darüber zu sein, was wir auswählen.

ID-Selektoren

ID-Selektoren sind eine Möglichkeit, ein Element auszuwählen, ohne ein anderes Element desselben Typs auszuwählen. Nehmen wir an, wir würden den HTML-Code in unserem <article>-Beispiel aktualisieren, sodass der erste Artikel mit einer ID “getaggt” wird

<article id="featured">
  <!-- Article 1 -->
</article>

<article>
  <!-- Article 2 -->
</article>

<article>
  <!-- Article 3 -->
</article>

Nun können wir diese ID verwenden, um den ersten Artikel von den anderen zu unterscheiden und Stile spezifisch darauf anzuwenden. Wir stellen dem ID-Namen ein Rautezeichen (#) voran, wenn wir unseren CSS-Selektor schreiben, um ihn richtig auszuwählen.

/* Selects all <article> elements */
article {
  background: #fff;
}

/* Selects any element with id="featured" */
#featured {
  background: hsl(35 100% 90%);
  border-color: hsl(35 100% 50%);
}

Da haben wir es, das lässt den ersten Artikel ein wenig mehr hervorstechen als die anderen!

Bevor Sie nun anfangen, überall in Ihrem HTML IDs hinzuzufügen, beachten Sie, dass IDs als eine grobschlächtige Methode zur Auswahl gelten. IDs sind so spezifisch, dass es schwierig ist, sie mit anderen Stilen in Ihrem CSS zu überschreiben. IDs haben so viel Spezifitätskraft, dass jeder Selektor, der versucht, sie zu überschreiben, mindestens ebenfalls eine ID benötigt. Sobald Sie fast an die Spitze der Leiter dieses Spezifitätskrieges gelangt sind, führt dies dazu, dass !important-Regeln usw. verwendet werden, die wiederum fast unmöglich zu überschreiben sind.

Ordnen wir unser CSS aus dem letzten Beispiel neu an, um das in Aktion zu sehen

/* Selects any element with id="featured" */
#featured {
  background: hsl(35 100% 90%);
  border-color: hsl(35 100% 50%);
}

/* Selects all <article> elements */
article {
  background: #fff;
}

Der ID-Selektor kommt nun vor dem Element-Selektor. Gemäß der Art und Weise, wie die CSS Cascade Stile bestimmt, könnten Sie erwarten, dass alle article-Elemente einen weißen Hintergrund erhalten, da diese Regel nach der Regel des ID-Selektors kommt. Aber das passiert nicht.

Sie sehen also, wie IDs in Bezug auf die Auswahl von Elementen ein wenig zu “spezifisch” sein mögen, da sie die Reihenfolge beeinflussen, in der die CSS Cascade Stile anwendet, und dies macht Stile schwieriger zu verwalten und zu pflegen.

Der andere Grund, IDs als Selektoren zu vermeiden? Technisch dürfen wir eine ID nur einmal auf einer Seite verwenden, pro ID. Mit anderen Worten, wir können ein Element mit #featured haben, aber nicht zwei. Das schränkt stark ein, was wir gestalten können, wenn wir diese Stile auf andere Elemente erweitern müssen – ganz zu schweigen von der Schwierigkeit, die Stile der ID zu überschreiben.

Ein besserer Anwendungsfall für IDs ist die Auswahl von Elementen in JavaScript – nicht nur, dass dies die Art von Stilkonflikten vermeidet, die wir oben gesehen haben, sondern es hilft auch, eine Trennung der Zuständigkeiten zwischen dem, was wir in CSS für das Styling auswählen, und dem, was wir in JavaScript für die Interaktion auswählen, aufrechtzuerhalten.

Eine weitere Sache zu ID-Selektoren: Die ID etabliert, was wir einen “Anker” nennen, was ein schicker Begriff dafür ist, dass wir direkt zu einem Element auf der Seite verlinken können. Zum Beispiel, wenn wir einen Artikel mit einer ID haben

<article id="featured">...</article>

…dann können wir wie folgt einen Link dazu erstellen

<a href="featured">Jump to article below ⬇️</a>

<!-- muuuuuuch further down the page. -->

<article id="featured">...</article>

Das Klicken auf den Link führt Sie zu dem Element, als ob der Link an diesem Element verankert wäre. Versuchen Sie genau das in der folgenden Demo

Dieses kleine HTML-Schmuckstück eröffnet einige ziemlich interessante Möglichkeiten, wenn wir ein wenig CSS einstreuen. Hier sind einige Artikel, um diese Möglichkeiten zu erkunden.

Klassen-Selektoren

Klassen-Selektoren sind vielleicht der am häufigsten verwendete CSS-Selektortyp im Web. Klassen sind ideal, da sie etwas spezifischer als Element-Selektoren sind, aber ohne die grobschlächtige Natur von IDs. Sie können eine detaillierte Erklärung lesen, wie die CSS Cascade die Spezifität bestimmt, aber das Folgende ist eine gekürzte Veranschaulichung, die sich spezifisch (verstehen Sie?!) auf die bisher behandelten Selektortypen konzentriert.

Showing element, class, and ID selectors in a horizontal row from least specific to most specific.

Das macht Klassen-Selektoren so beliebt – sie sind nur geringfügig spezifischer als Elemente, aber halten die Spezifität niedrig genug, um handhabbar zu sein, wenn wir Stile in einer Regel mit Stilen in einer anderen überschreiben müssen.

Der einzige Unterschied beim Schreiben einer Klasse ist, dass wir einen Punkt (.) vor den Klassennamen stellen, anstatt eines Rautezeichens (#).

/* Selects all <article> elements */
article {
  background: #fff;
}

/* Selects any element with class="featured" */
.featured {
  background: hsl(35 100% 90%);
  border-color: hsl(35 100% 50%);
}

So sieht unser <article>-Beispiel aus, wenn wir #featured durch .featured ersetzen.

Gleiches Ergebnis, bessere Spezifität. Und ja, wir können verschiedene Selektortypen absolut auf demselben Element kombinieren

<article id="someID" class="featured">...</article>

Sehen Sie all die Möglichkeiten, die wir haben, um ein <article> auszuwählen? Wir können es auswählen nach

  • Seinem Elementtyp (article)
  • Seiner ID (#someID)
  • Seiner Klasse (.featured)

Die folgenden Artikel geben Ihnen clevere Ideen für die Verwendung von Klassen-Selektoren in CSS.

Aber wir haben noch mehr Möglichkeiten, Elemente auf diese Weise auszuwählen, also machen wir weiter.

Attribut-Selektoren

ID- und Klassen-Selektoren fallen technisch in diese Attribut-Selektoren-Kategorie. Wir nennen sie “Attribute”, weil sie im HTML vorhanden sind und mehr Kontext über das Element liefern. Alle folgenden sind Attribute in HTML

<!-- ID, Class, Data Attribute -->
<article id="#id" class=".class" data-attribute="attribute">
</article>

<!-- href, Title, Target -->
<a href="https://css-tricks.de" title="Visit CSS-Tricks" target="_blank"></a>

<!-- src, Width, Height, Loading -->
<img src="star.svg" width="250" height="250" loading="laxy" >

<!-- Type, ID, Name, Checked -->
<input type="checkbox" id="consent" name="consent" checked />

<!-- Class, Role, Aria Label -->
<div class="buttons" role="tablist" aria-label="Tab Buttons">

Alles mit einem Gleichheitszeichen (=), gefolgt von einem Wert in diesem Beispielcode, ist ein Attribut. Wir können also technisch alle Links mit einem href-Attribut stylen, das gleich https://css-tricks.de ist

a[href="https://css-tricks.de"] {
  color: orangered;
}

Beachten Sie die Syntax? Wir verwenden eckige Klammern ([]), um ein Attribut auszuwählen, anstatt eines Punkts oder einer Raute, wie wir es bei Klassen und IDs tun.

Das Gleichheitszeichen, das in Attributen verwendet wird, deutet darauf hin, dass wir mehr tun können, um Elemente auszuwählen, als etwas zu finden, das exakt dem Wert entspricht. Das ist tatsächlich der Fall. Zum Beispiel können wir sicherstellen, dass der passende Selektor groß- oder kleingeschrieben wird. Eine gute Verwendung dafür könnte die Auswahl von Elementen mit dem href-Attribut sein, solange sie keine Großbuchstaben enthalten

/* Case sensitive */
a[href*='css-tricks' s] {}

Das s darin sagt CSS, dass wir nur einen Link mit einem href-Attribut auswählen wollen, der keine Großbuchstaben enthält.

<!-- 👎 No match -->
<a href="https://css-tricks.de">...</a>

<!-- 👍 Match! -->
<a href="https://css-tricks.de">...</a>

Wenn die Groß-/Kleinschreibung keine Rolle spielt, können wir das CSS auch darauf hinweisen

/* Case insensitive */
a[href*='css-tricks' i] {}

Nun wird eines der beiden Link-Beispiele übereinstimmen, unabhängig davon, ob im href-Attribut Groß- oder Kleinbuchstaben vorhanden sind.

<!-- 👍 I match! -->
<a href="https://css-tricks.de">...</a>

<!-- 👍 I match too! -->
<a href="https://css-tricks.de">...</a>

Es gibt viele, viele verschiedene Arten von HTML-Attributen. Schauen Sie sich unbedingt unseren Data Attributes Guide an, um eine vollständige Übersicht über nicht nur [data-attribute], sondern auch wie sie sich auf andere Attribute beziehen und wie man sie mit CSS stylt.

Universeller Selektor

CSS-Tricks hat eine besondere Beziehung zum Universal-Selektor – es ist unser Logo!

Das stimmt, das Sternchen-Symbol (*) ist ein eigenständiger Selektor, dessen Zweck darin besteht, alles auszuwählen. Ganz buchstäblich können wir mit diesem einen kleinen Sternchen alles auf einer Seite auswählen – jedes einzelne Element. Beachten Sie, dass ich jedes einzelne Element gesagt habe, also werden IDs, Klassen oder sogar Pseudo-Elemente nicht erfasst. Es ist der Element-Selektor zum Auswählen aller Elemente.

/* Select ALL THE THINGS! 💥 */
* {
  /* Styles */
}

Oder wir können ihn mit einem anderen Selektortyp verwenden, um alles innerhalb eines bestimmten Elements auszuwählen.

/* Select everything in an <article> */
article * {
  /* Styles */
}

Das ist eine praktische Möglichkeit, alles in einem <article> auszuwählen, selbst wenn Sie in Zukunft weitere Elemente in dieses Element im HTML einfügen. Die Zeiten, in denen der Universal-Selektor am häufigsten verwendet wird, sind, um border-sizing für alle Elemente generell festzulegen, einschließlich aller Elemente und Pseudo-Elemente.

*,
*::before,
*::after {
  box-sizing: border-box;
}

Es gibt einen guten Grund, warum dieser CSS-Schnipsel in vielen Stylesheets landet, was Sie in den folgenden Artikeln nachlesen können.

Manchmal ist der Universal-Selektor impliziert. Zum Beispiel, wenn ein Pseudo-Selektor am Anfang eines neuen Selektors verwendet wird. Diese wählen genau dasselbe aus

*:has(article) { }
:has(article)  { }

Pseudo-Selektoren

Pseudo-Selektoren sind zum Auswählen von Pseudo-Elementen da, genau wie Element-Selektoren zum Auswählen von Elementen. Und ein Pseudo-Element ist wie ein Element, aber es erscheint nicht tatsächlich im HTML. Wenn Pseudo-Elemente für Sie neu sind, haben wir eine kurze Erklärung, auf die Sie sich beziehen können.

Jedes Element hat ein ::before und ::after Pseudo-Element, das damit verbunden ist, obwohl wir es im HTML nicht sehen können.

<div class="container">
  <!-- ::before psuedo-element here -->
  <div>Item</div>
  <div>Item</div>
  <div>Item</div>
  <!-- ::after psuedo-element here -->
</div>

Diese sind super praktisch, da sie zusätzliche Möglichkeiten bieten, in ein Element einzuhaken und zusätzliche Stile anzuwenden, ohne mehr Markup zum HTML hinzuzufügen. Halten Sie die Dinge so sauber wie möglich, richtig?!

Wir wissen, dass ::before und ::after Pseudo-Elemente sind, weil sie von einem Doppelpunktpaar (::) vorangestellt werden. So wählen wir sie auch aus!

.container::before {
  /* Styles */
}

Die Pseudo-Elemente ::before und ::after können auch mit einem einzelnen Doppelpunkt geschrieben werden – d. h. :before und :after – aber es ist immer noch üblicher, einen Doppelpunkt zu sehen weil er hilft, Pseudo-Elemente von Pseudo-Klassen zu unterscheiden.

Aber es gibt einen Haken bei der Verwendung von Pseudo-Selektoren: sie erfordern die content-Eigenschaft. Das liegt daran, dass Pseudos keine “echten” Elemente sind, sondern solche, die in Bezug auf HTML nicht existieren. Das bedeutet, sie benötigen Inhalt, der angezeigt werden kann… selbst wenn es leerer Inhalt ist

.container::before {
  content: "";
}

Natürlich, wenn wir Wörter in der content-Eigenschaft angeben würden, würden diese auf der Seite angezeigt werden.


Komplexe Selektoren

Komplexe Selektoren brauchen vielleicht ein wenig Marketing-Hilfe, denn “komplex” ist ein furchtbar beängstigender Begriff, auf den man stößt, wenn man am Anfang des Lernens dieser Dinge steht. Während Selektoren tatsächlich komplex und unübersichtlich werden können, ist die allgemeine Idee super einfach: Wir können mehrere Selektoren in derselben Regel kombinieren.

Betrachten wir drei verschiedene Wege, wie wir diese “nicht so komplexen” komplexen Selektoren schreiben können.

Liste von Selektoren

Zunächst einmal ist es möglich, Selektoren so zu kombinieren, dass sie dieselben Stile teilen. Wir trennen einfach jeden Selektor mit einem Komma.

.selector-1,
.selector-2,
.selector-3 {
  /* We share these styles! 🤗 */
}

Das sieht man oft beim Gestalten von Überschriften – die tendieren dazu, die gleichen allgemeinen Stile zu haben, außer vielleicht der font-size.

h1,
h2,
h3,
h4,
h5,
h6 {
  color: hsl(25 80% 15%);
  font-family: "Poppins", system-ui;
}

Ein Zeilenumbruch zwischen den Selektoren kann die Lesbarkeit verbessern. Sie können sich wahrscheinlich vorstellen, wie komplex und unübersichtlich das werden kann. Hier ist zum Beispiel einer

section h1, section h2, section h3, section h4, section h5, section h6, 
article h1, article h2, article h3, article h4, article h5, article h6, 
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, 
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {
  color: #BADA55;
}

Ähm, okay. Niemand will das in seinem Stylesheet haben. Es ist schwer zu sagen, was genau ausgewählt wird, oder?

Die gute Nachricht ist, dass wir moderne Wege haben, diese Selektoren effizienter zu kombinieren, wie zum Beispiel den Pseudo-Selektor :is(). In diesem Beispiel bemerken Sie, dass wir technisch gesehen alle dieselben Elemente auswählen. Wenn wir die vier section-, article-, aside- und nav-Element-Selektoren entfernen und die Nachkommen beibehalten würden, hätten wir dies

h1, h2, h3, h4, h5, h6, 
h1, h2, h3, h4, h5, h6,
h1, h2, h3, h4, h5, h6, 
h1, h2, h3, h4, h5, h6, {
  color: #BADA55;
}

Der einzige Unterschied ist, auf welches Element diese Überschriften beschränkt sind. Hier ist :is() praktisch, da wir diese vier Elemente so matchen können

:is(section, article, aside, nav) {
  color: #BADA55;
}

Das wendet color auf die Elemente selbst an, aber was wir wollen, ist, es auf die Überschriften anzuwenden. Anstatt diese für jede Überschrift aufzulisten, können wir wieder :is() verwenden, um sie auf einmal auszuwählen

/* Matches any of the following headings scoped to any of the following elements.  */
:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
  color: #BADA55;
}

Während wir über :is() sprechen, ist es erwähnenswert, dass wir auch den Pseudo-Selektor :where() haben und dass er genau dasselbe tut wie :is(). Der Unterschied? Die Spezifität von :is() entspricht der Spezifität des spezifischsten Elements in der Liste. :where() hingegen hat null Spezifität. Wenn Sie also einen komplexen Selektor wie diesen wünschen, der leichter zu überschreiben ist, wählen Sie stattdessen :where().

Verschachtelte Selektoren

Das letzte Beispiel, das zeigt, wie :is() verwendet werden kann, um effizientere komplexe Selektoren zu schreiben, ist gut, aber wir können es jetzt noch besser machen, da CSS-Verschachtelung eine weit verbreitete Funktion ist.

Diese Browser-Unterstützungsdaten stammen von Caniuse, das mehr Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.

Desktop

ChromeFirefoxIEEdgeSafari
120117Nein12017.2

Mobil / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712717.2

CSS-Verschachtelung ermöglicht es uns, die Beziehung zwischen Selektoren besser zu erkennen. Wissen Sie, wie wir die Beziehung zwischen Elementen in HTML klar erkennen, wenn wir nachfolgende Elemente einrücken?

<!-- Parent -->
<article>
  <!-- Child -->
  <img src="" alt="...">
  <!-- Child -->
  <div class="article-content">
    <!-- Grandchild -->
    <h2>Title</h2>
    <!-- Grandchild -->
    <p>Article content.</p>
  </div>
</article>

CSS-Verschachtelung ist eine ähnliche Methode, mit der wir CSS-Regeln formatieren können. Wir beginnen mit einer übergeordneten Regel und betten dann nachfolgende Regeln ein. Wenn wir also das <h2>-Element im letzten HTML-Beispiel auswählen würden, könnten wir einen nachfolgenden Selektor wie diesen schreiben

article h2 { /* Styles */ }

Mit Verschachtelung

article  {
  /* Article styles */

  h2 { /* Heading 2 styles */ }
}

Sie haben wahrscheinlich bemerkt, dass wir technisch eine Ebene tiefer gehen können, da die Überschrift in einem anderen .article-content-Element enthalten ist

article  {
  /* Article styles */

  .article-content {
    /* Container styles */

    h2 { /* Heading 2 styles */ }
  }
}

Alles in allem ist das Auswählen der Überschrift mit Verschachtelung gleichbedeutend mit dem Schreiben eines nachfolgenden Selektors in einer flachen Struktur

article .article-content h2 { /* Heading 2 styles */ }

Sie fragen sich vielleicht, wie es überhaupt möglich ist, einen verketteten Selektor im Verschachtelungsformat zu schreiben. Ich meine, wir könnten leicht einen verketteten Selektor in einen anderen Selektor verschachteln

article  {
  /* Article styles */

  h2.article-content {
    /* Heading 2 styles */
  }
}

Aber es ist nicht so, dass wir den article-Element-Selektor als verschachtelten Selektor neu deklarieren können

article  {
  /* Article styles */

  /* Nope! 👎 */
  article.article-element {
    /* Container styles */  

    /* Nope! 👎 */
    h2.article-content {
      /* Heading 2 styles */
    }
  }
}

Selbst wenn wir das könnten, würde das irgendwie den Zweck einer ordentlich organisierten Verschachtelung zunichtemachen, die die Beziehungen zwischen den Selektoren zeigt. Stattdessen können wir das Ampersand-Symbol (&) verwenden, um den Selektor darzustellen, in den wir verschachteln. Wir nennen das den Verschachtelungsselektor.

article  {

  &.article-content {
    /* Equates to: article.article-content */
  }
}

Zusammensetzende Selektoren

Wir haben ziemlich viel über die Cascade gesprochen und wie sie bestimmt, welche Stile mit einem Spezifitätswert auf passende Selektoren angewendet werden. Wir haben bereits gesehen, wie ein Element-Selektor weniger spezifisch ist als ein Klassen-Selektor, der weniger spezifisch ist als ein ID-Selektor und so weiter.

article { /* Specificity: 0, 0, 1 */ }
.featured { /* Specificity: 0, 1, 0 */ }
#featured { /* Specificity: 1, 0, 0 */ }

Nun, wir können die Spezifität erhöhen, indem wir Selektoren verketten oder “zusammensetzen”. Auf diese Weise geben wir unserem Selektor eine höhere Priorität, wenn es um die Bewertung von zwei oder mehr passenden Stilen geht. Wiederum ist das Überschreiben von ID-Selektoren unglaublich schwierig, daher werden wir mit den Element- und Klassen-Selektoren arbeiten, um verkettete Selektoren zu veranschaulichen.

Wir können unseren article-Element-Selektor mit unserem .featured-Klassen-Selektor verketten, um einen höheren Spezifitätswert zu erzeugen.

article { /* Specificity: 0, 0, 1 */ }
.featured { /* Specificity: 0, 1, 0 */ }

articie.featured { /* Specificity: 0, 1, 1 */ }

Dieser neue zusammengesetzte Selektor ist spezifischer (und leistungsfähiger!) als die beiden einzelnen Selektoren. Beachten Sie in der folgenden Demo, wie der zusammengesetzte Selektor vor den beiden einzelnen Selektoren im CSS steht und sie dennoch schlägt, wenn die Cascade ihre Spezifitätswerte auswertet.

Interessanterweise können wir “gefälschte” Klassen in verketteten Selektoren als Strategie zur Verwaltung der Spezifität verwenden. Nehmen Sie dieses reale Beispiel

.wp-block-theme-button .button:not(.specificity):not(.extra-specificity) { }

Wow, oder? Da passiert viel. Aber die Idee ist folgende: Die .specificity und .extra-specificity Klassen-Selektoren sind nur dazu da, die Spezifität des .wp-block-theme .button-Nachfolgerselektors zu erhöhen. Vergleichen wir den Spezifitätswert mit und ohne diese künstlichen Klassen (die :not() in die Übereinstimmung einbeziehen).

.wp-block-theme-button .button {
  /* Specificity: 0, 2, 0 */
}

.wp-block-theme-button .button:not(.specificity) {
  /* Specificity: 0, 3, 0 */
}

.wp-block-theme-button  .button:not(.specificity):not(.extra-specificity {
  /* Specificity: 0, 4, 0 */
}

Interessant! Ich bin mir nicht sicher, ob ich das in meinem eigenen CSS verwenden würde, aber es ist eine weniger grobschlächtige Methode, als auf das !important-Schlüsselwort zurückzugreifen, das genauso schwer zu überschreiben ist wie ein ID-Selektor.


Kombinatoren

Wenn Selektoren “was” wir in CSS auswählen sind, dann könnten Sie CSS-Kombinatoren als “wie” wir sie auswählen betrachten. Sie werden verwendet, um Selektoren zu schreiben, die andere Selektoren kombinieren, um Elemente anzuvisieren. Inception!

Der Name “Kombinator” ist ausgezeichnet, weil er die vielen verschiedenen Wege, auf denen wir Selektoren kombinieren können, genau wiedergibt. Warum sollten wir Selektoren kombinieren müssen? Wie wir bereits bei verketteten Selektoren besprochen haben, gibt es zwei gängige Situationen, in denen wir das tun möchten

  • Wenn wir die Spezifität dessen, was ausgewählt wird, erhöhen wollen.
  • Wenn wir ein Element basierend auf einer Bedingung auswählen wollen.

Lassen Sie uns die vielen Arten von Kombinatoren durchgehen, die in CSS verfügbar sind, um diese beiden Situationen zusätzlich zu verketteten Selektoren zu berücksichtigen.

Nachkommenschafts-Kombinator

Wir nennen ihn “Nachkommenschafts”-Kombinator, weil wir ihn verwenden, um Elemente innerhalb anderer Elemente auszuwählen, so ähnlich wie hier

/* Selects all elements in .parent with .child class */
.parent .child {}

…was alle Elemente mit der Klasse .child im folgenden HTML-Beispiel auswählen würde

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>

  <div class="friend"></div>

  <div class="child"></div>
  <div class="child"></div>
</div>

Sehen Sie dieses Element mit dem Klassennamen .friend? Das ist das einzige Element innerhalb des .parent-Elements, das nicht mit dem .parent .child {}-Nachkommenschafts-Kombinator ausgewählt wird, da es nicht mit .child übereinstimmt, obwohl es auch ein Nachkomme des .parent-Elements ist.

Kind-Kombinator

Ein Kind-Kombinator ist im Grunde eine Abzweigung des Nachkommenschafts-Kombinators, nur ist er spezifischer als der Nachkommenschafts-Kombinator, weil er nur direkte Kinder eines Elements auswählt, anstatt jegliche Nachkommen.

Lassen Sie uns das letzte HTML-Beispiel, das wir uns angesehen haben, überarbeiten, indem wir ein Nachkommenschafts-Element einführen, das tiefer in den Stammbaum geht, wie z. B. ein .grandchild

<div class="parent">
  <div class="child"></div>
  <div class="child">
    <div class="grandchild"></div>
  </div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Was wir also haben, ist ein .parent für vier .child-Elemente, von denen eines ein .grandchild-Element enthält.

Vielleicht möchten wir das .child-Element auswählen, ohne unbeabsichtigt das .grandchild des zweiten .child-Elements auszuwählen. Das kann ein Kind-Kombinator tun. Alle folgenden Kind-Kombinatoren würden dasselbe erreichen

/* Select only the "direct" children of .parent */
.parent > .child {}
.parent > div {}
.parent > * {}

Sehen Sie, wie wir verschiedene Selektortypen kombinieren, um eine Auswahl zu treffen? Wir kombinieren, verdammt! Wir tun es nur auf leicht unterschiedliche Weise, basierend auf der Art des Kind-Selektors, den wir kombinieren.

/* Select only the "direct" children of .parent */
.parent > #child { /* direct child with #child ID */
.parent > .child { /* direct child with .child class */ }
.parent > div { /* direct child div elements */ }
.parent > * { /* all direct child elements */ }

Es ist ziemlich genial, dass wir nicht nur eine Möglichkeit haben, nur die direkten Kinder eines Elements auszuwählen, sondern auch mehr oder weniger spezifisch zu sein, basierend auf der Art des Selektors. Zum Beispiel ist der ID-Selektor spezifischer als der Klassen-Selektor, der spezifischer ist als der Element-Selektor und so weiter.

Allgemeiner Geschwister-Kombinator

Wenn zwei Elemente denselben Elternelement teilen, macht sie das zu Geschwistern wie Bruder und Schwester. Wir haben ein Beispiel dafür im Vorbeigehen gesehen, als wir den Nachkommenschafts-Kombinator besprochen haben. Lassen Sie uns die Klassennamen aus diesem Beispiel überarbeiten, um die Geschwisterbeziehung etwas klarer zu machen

<div class="parent">
  <div class="brother"></div>
  <div class="sister"></div>
</div>

So können wir das Element .sister auswählen, solange es einem Geschwister mit der Klasse .brother vorangestellt ist.

/* Select .sister only if follows .brother */
.brother ~ .sister { }

Das Tildesymbol (~) teilt uns mit, dass es sich um einen Geschwister-Kombinator handelt.

Es spielt keine Rolle, ob ein .sister unmittelbar nach einem .brother kommt oder nicht – solange ein .sister nach einem .brother kommt und sie dasselbe Elternelement teilen, wird es ausgewählt. Sehen wir uns ein komplizierteres HTML-Beispiel an

<main class="parent">
  
  <!-- .sister immediately after .brother -->
  <div class="brother"></div>
  <div class="sister"></div>

  <!-- .sister immediately after .brother -->
  <div class="brother"></div>
  <div class="sister"></div>
  <!-- .sister immediately after .sister -->
  <div class="sister"></div>

  <!-- .cousin immediately after .brother -->
  <div class="brother"></div>
  <div class="cousin">
    <!-- .sister contained in a .cousin -->
    <div class="sister"></div>
  </div>
</main>

Der Geschwister-Kombinator, den wir geschrieben haben, wählt nur die ersten drei .sister-Elemente aus, da sie die einzigen sind, die nach einem .brother-Element kommen und denselben Elternteil teilen – selbst im Fall des dritten .sister, das nach einer anderen Schwester kommt! Die vierte .sister ist in einem .cousin enthalten, was verhindert, dass sie mit dem Selektor übereinstimmt.

Sehen wir uns das im Kontext an. Wir können also alle Elemente mit einem Element-Selektor auswählen, da jedes Element im HTML ein div ist

Von dort aus können wir nur die Brüder mit einem Klassen-Selektor auswählen, um ihnen eine andere Hintergrundfarbe zu geben

Wir können auch einen Klassen-Selektor verwenden, um eine andere Hintergrundfarbe auf alle Elemente mit der Klasse .sister anzuwenden

Und schließlich können wir einen allgemeinen Geschwister-Kombinator verwenden, um nur Schwestern auszuwählen, die unmittelbar nach einem Bruder kommen.

Haben Sie bemerkt, wie sich die Hintergrundfarbe des letzten .sister-Elements grün gefärbt hat, während die anderen lila wurden? Das liegt daran, dass es die einzige .sister in der Gruppe ist, die nicht denselben .parent wie ein .brother-Element teilt.

Benachbarter Kombinator

Glauben Sie es oder nicht, wir können sogar noch spezifischer darin werden, welche Elemente wir mit einem benachbarten Kombinator auswählen. Der allgemeine Geschwister-Selektor, den wir gerade betrachtet haben, wählt alle .sister-Elemente auf der Seite aus, solange es denselben Elternteil wie .brother teilt und nach dem .brother kommt.

Was einen benachbarten Kombinator ausmacht, ist, dass er jedes Element auswählt, das unmittelbar einem anderen folgt. Erinnern Sie sich, warum die letzte .sister nicht übereinstimmte, weil sie in einem anderen Elternelement (d. h. .cousin) enthalten ist? Nun, wir können sie tatsächlich einzeln mit einem benachbarten Kombinator auswählen

/* Select .sister only if directly follows .brother */
.brother + .sister { }

Beachten Sie, was passiert, wenn wir das zu unserem letzten Beispiel hinzufügen

Die ersten beiden .sister-Elemente haben ihre Farbe geändert! Das liegt daran, dass sie die einzigen Schwestern sind, die direkt nach einem .brother kommen. Die dritte .sister kommt direkt nach einer anderen .sister, und die vierte ist in einem .cousin enthalten, was beide davon abhält, mit der Auswahl übereinzustimmen.


Mehr über CSS-Selektoren erfahren


Referenzen

Der Großteil dessen, was Sie hier lesen, sind Informationen aus Artikeln, die wir auf CSS-Tricks veröffentlicht haben und die im gesamten Leitfaden verlinkt sind. Zusätzlich zu diesen Artikeln waren die folgenden Ressourcen äußerst hilfreich bei der Erstellung dieses Leitfadens.