Selektoren in CSS/Einstieg

Aus SELFHTML-Wiki
Selektoren in CSS(Weitergeleitet von Selektor-Liste)
Wechseln zu: Navigation, Suche

Selektoren sind Muster, mit denen HTML-Elemente ausgewählt werden, damit man ihnen Stile zuweisen kann.

CSS-Regelsatz.svg

Der Selektor ist somit der Teil vor den geschweiften Klammern.

Einfache Selektoren

Universalselektor

Das Sternzeichen „*“ (der Asterisk) ist der Universalselektor. Mit ihm werden alle Elemente in einem Dokument angesprochen.

* - der Universalselektor ansehen …
* {
  border: medium solid green;
}
*, ::before, ::after { 
  box-sizing: border-box; 
}

Im Beispiel werden alle Elemente mit einer Randlinie versehen, was in der Praxis so niemand tun wird.

Mit dem Universalselektor kann man Elemente normalisieren, z. B. mit box-sizing das Box-Modell, das ja Randlinien zu den Breitenangaben dazuzählt, auf den intuitiveren QuirksMode umschalten.

In Verbindung mit anderen Selektoren ist der Universalselektor oft überflüssig. Auch erhöht er nicht die Spezifität des Selektors.

Typ-Selektor

Der Element- bzw. Typselektor besteht aus dem Namen des Elements, das angesprochen werden soll. Mit diesem Selektor werden alle Elemente eines Typs angesprochen.[1]

Typselektor ansehen …
h1 { 
  color: red; 
}
h1, h2 { 
  background-color: #ccc;
  border-radius: .5em; 
}

Der erste Regelsatz besteht aus einem Selektor h1, der allen h1-Elementen die Textfarbe rot zuweist.

Der zweite Regelsatz besteht aus einer Selektor-Liste mit zwei voneinander unabhängigen Selektoren h1 und h2, die alle Überschriften vom Typ h1 und h2 anspricht.

Klassen-Selektor

Häufig will man jedoch nicht alle, sondern nur eins oder einige Elemente speziell formatieren. In HTML, aber auch in SVG und MathML kann man Elementen ein Klassen-Attribut geben.

Ein Klassenselektor wird gebildet, indem vor dem Klassennamen ein Punkt notiert wird.

Klassen müssen nicht zu gleichen Elementen gehören ansehen …
.warning {
  background-color: #ffe0e0;
  border-left: thick solid #c82f04;
  padding: 0.5em;
  margin-bottom: 1em;
}

.example {
  background-color: #f9eed2;
  border-left: thick solid gold;
  padding: 0.5em;
  margin-bottom: 1em;
}

Die ersten drei Absätze erhalten Klassen und werden so formatiert. Allerdings erhält auch das div-Element die Klasse .warning und damit das Aussehen der Warnhinweise.

Beachte:
Klassennamen sollten nach ihrer Funktion (z.B. „Hinweis“) benannt werden und nicht nach den Formatierungen, die sie beinhalten. So stellen sie sicher, dass die Klasse auch nach einer Überarbeitung der Gestaltung noch nachvollziehbar den Bestandteilen eines Dokuments zugeordnet werden kann.
Viele informelle Eigenschaften eines Elements können durch elementspezifische Attribute abgedeckt werden. CSS erlaubt das Ansprechen von Elementen anhand ihrer Attribute. Klassen und Klassenselektoren sollten Sie daher nur dann einsetzen, wenn keine andere Zuordnungsmöglichkeit besteht.

ID-Selektor

Mit dem ID-Selektor kann ein Element angesprochen werden, dem eine ID mit dem id-Attribut zugeordnet wurde. Ein ID-Selektor wird gebildet, indem das Gatterzeichen „#“ vor den ID-Namen gestellt wird.

der Header - einzigartig ansehen …
#main-header {
  font-size: 1.8rem;
  color: navy;
  background-color: skyblue;
  padding: 1em;
  border: thin solid;
}

In oberem Beispiel erhält das Element h1 die ID „main-header“. Die CSS-Regeln bewirken, dass dieses einen hellblauen Hintergund, dunkelblaue Schriftfarbe und einen Rand erhält.

Beachte: Eine ID darf in einem Dokument nur ein einziges Mal vorkommen, die Kombination des ID-Selektors mit anderen Selektoren ergibt nur dann Sinn, wenn man die entsprechende ID in mehreren Dokumenten und in unterschiedlichen Situationen einsetzt.

Umgang mit IDs, die spezielle Zeichen enthalten

Aus Sicht von CSS ist eine ID ein CSS-Identifier und muss folgenden Regeln folgen:

  • Beginnt mit einem ASCII Buchstaben (A-Z, a-z)
  • Besteht im Übrigen aus den ASCII Zeichen a-z, A-Z, 0-9, "-" und "_", sowie allen Unicode-Zeichen ab U+0080.

Eine ID in HTML unterliegt wesentlich geringeren Einschränkungen. Während HTML 4 hier noch den Regeln von CSS ähnlich war, gibt es in HTML 5 fast gar keine Beschränkungen mehr, außer, dass eine ID kein Whitespace enthalten darf. Solche IDs können in CSS angesprochen werden, dafür müssen aber alle Zeichen, die die Regeln für CSS-Identifier verletzen, als CSS-Escape-Sequenz geschrieben werden.

Beispiel
<style>
#\31 234 {
  color: red;
}
</style>
...
<p id="1234">Dieser Text erscheint rot.</p>

Attribut-Selektor

CSS-Attributselektoren wählen Elemente aus, die ein bestimmtes Attribut explizit gesetzt haben, mit Optionen zur Definition einer Attributwert- oder Teilzeichenfolgenwertübereinstimmung.

Attributspräsenz

Ein Element, das ein bestimmtes Attribut besitzt, kann durch den einfachen Attribut-Selektor angesprochen werden, indem eckige Klammern („[“ und „]“) um den Namen des Attributs gesetzt werden.

Attributpräsenz
[aria-hidden] {
  opacity: 0.4;
  font-style: italic;
}

Alle Elemente, die ein aria-hidden Attribut haben, werden mit opacity ausgegraut.

Beachte: Ob die Groß- und Kleinschreibung des Attributnamens beachtet wird, hängt davon ab, ob man CSS für HTML oder für XML verwendet. Bei HTML wird sie nicht beachtet, bei XML (z. B. viewBox in SVG-Dokumenten) hingegen schon.

Selektion nach Wert

Attributselektoren erlauben es auch, nur diejenigen Elemente auszuwählen, bei denen ein Attribut einen bestimmten Wert besitzt:

Elemente nach Attributwerten selektieren ansehen …
button[aria-expanded="true"] {
  background-color: #d0f0d0;
  border-color: green;
}

button[aria-expanded="false"] {
  background-color: #f8e0e0;
  border-color: red;
}

button[aria-expanded="true"] + #myPopover {
  display: block;
}

Das button-Element erhält keine Klassen sondern ein aria-expanded-Attribut. Wenn dieser Button angeklickt wird, ändert sich der Wert seines aria-expanded-Attributs. Dies wird mit [aria-expanded="false"] bzw. [aria-expanded="true"] entsprechend selektiert und der Button ändert seine Farbe.

Der letzte Regelsatz button[aria-expanded="true"] + #myPopover verknüpft den Attributswert und die ID des nachfolgenden Elements mit einem Nachbar-Kombinator und lässt das Popover mit diplay:block erscheinen.

Beachte:
  • Der Vergleichswert muss entweder in Anführungszeichen gesetzt werden, oder den CSS-Namensregeln entsprechen. Wenn Du dir unsicher bist, setze einfach immer Anführungszeichen.
  • Ob die Groß- und Kleinschreibung des Attributwertes beachtet wird, hängt vom abgefragten Attribut ab. Die HTML Spezifikation listet diejenigen Attribute auf, bei denen die Schreibung nicht beachtet wird.[2] Dies sind typischerweise Attribute, deren Werte Schlüsselwörter darstellen. Bei allen anderen Attributen wird die Schreibung beachtet (z. B. id, class oder role).


Attributselektoren erlauben es auch, nur diejenigen Elemente auszuwählen, bei denen ein Attribut einen bestimmten Wert besitzt: oder einen bestimmten Wertabschnitt besitzt. Dafür erweitert man die einfache Präsenzabfrage um einen Vergleichsoperator und den Vergleichswert.

[name=wert] - vollständige Übereinstimmung
trifft nur auf diejenigen Elemente zu, deren Attribut exakt den angegebenen Wert hat.
[name~=wert] - Wert ist Teil einer durch Leerzeichen separierten Liste
trifft zu, wenn der genannte Wert Teil der Werteliste im Attribut name ist. Die Einträge dieser Liste müssen durch Leerzeichen getrennt sein. Ein Beispiel für ein solches Listenattribut ist class (wobei man Klassen natürlich besser mit dem Klassenselektor abfragt).
[name|=wert] - Übereinstimmung bis zum ersten --Zeichen
Der Selektor verhält sich ähnlich wie [name=wert], der Vergleich geht aber nur bis zum ersten --Zeichen im Attributwert. Ist kein --Zeichen enthalten, wird vollständig verglichen. Diese Art der Abfrage bietet sich beispielsweise für Sprachcodes (de-at) an.
[name^=wert] - Übereinstimmung mit dem Anfang des Attributwerts
trifft zu, wenn der Attributwert mit dem angegebenen Wert beginnt
[name$=wert] - Übereinstimmung mit dem Ende des Attributwerts
trifft zu, wenn der Attributwert mit dem angegebenen Wert endet
[name*=wert] - Übereinstimmung mit einem Teil des Attributwerts
trifft zu, wenn der Attributwert den angegebenen Wert an einer beliebigen Stelle enthält


PDFs mit Teilübereinstimmung-Selektor finden und stylen ansehen …
a[href$=".pdf"]::after {
  content: "";
  display: inline-block;
  width: 1.5em;
  aspect-ratio: 1;
  padding-left: 0.5em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath ...");
  background-size: contain;
  background-repeat: no-repeat;
}

Im Beispiel finden sich zwei normale Links, die im href-Attribut auf PDF-Dokumente verlinken. Mit CSS werden sie über den Teilübereinstimmung-Selektor aufgrund der Dateiendung .pdf ([href$=".pdf"]) ausgewählt, das heißt selektiert.

Sie erhalten mit ::after nun ein Pseudoelement, das als Hintergrundbild das PDF-Icon als SVG enthält.

HTML/Tutorials/Links
Links auf unterschiedliche Dokumenttypen kennzeichnen

Beachte: Gibt man als Wert innerhalb dieser Selektoren die leere Zeichenkette an (z. B. [attribut*=""]), spricht der Selektor kein Element an.
Beachte:
  • In HTML gibt es boolesche Attribute, denen kein Wert zugewiesen werden muss, z. B. das checked-Attribut bei input-Elementen.
    Prüfe solche Attribute nur auf Attributpräsenz, nicht auf einen Wert!
  • Ein boolesches Attribut stellt nicht immer den aktuellen Zustand eines Elements dar. Eine Checkbox mit dem Attribut checked, behält das Attribut, auch wenn die Checkbox abgewählt wird.
    Verwende die Pseudoklasse :checked. In einem <details>-Element stellt das open-Attribut hingegen dar, ob das Element aufgeklappt ist oder nicht.

case-Sensitivität

Wie schon erwähnt, ist für bestimmte Attributwerte in HTML die Groß- und Kleinschreibung relevant (case-sensitiv). Beispielsweise bezeichnen die Klassennamen foo und Foo verschiedene Klassen.

Man kann in Attributselektoren mithilfe des Flags i oder s festlegen, ob der Vergleich des Attributwertes – unabhängig von den Vorgaben des jeweiligen Attributes – unter Beachtung der Schreibweise stattfinden soll oder nicht. Den zu vergleichenden Attributwert muss man dann in Anführungszeichen notieren.

Beachte: Diese Flags wirken nur auf den ASCII-Zeichensatz, also a-z und A-Z. Akzentzeichen und Umlaute sind außerhalb des ASCII-Bereichs und werden stets case-sensitiv verglichen.
Beispiel ansehen …
[class="warning"] { 
  color: red;
}
[class="warning" i] {
  background-color: lightgray; 
}
<div class="warning">warning</div>
<div class="Warning">Warning</div>
<div class="WARNING">WARNING</div>

Nur im ersten div-Element ist die Schriftfarbe rot, weil nur dieses der Klasse warning angehört. Alle div-Elemente hingegen haben einen grauen Hintergrund.

Die i- und s-Flags kann man in allen Attributwertselektoren verwenden.

Anwendung

In der Praxis ist oftmals günstiger, Selektoren zu kombinieren, um trennscharf den gewünschten Stil festzulegen, ohne allen Elementen eine Klasse oder sogar eine ID zu geben, was der Idee hinter den „zentralen Formaten“ wiederspricht.

angeblicher Screenshot einer mit Bootstrap formatierten Seite

Empfehlung: Auch wenn dieser im Internet verbreitete Screenshot einer angeblich mit Bootstrap geschriebenen Seite wahrscheinlich nicht echt ist, sollte man die Verwendung einer Vielzahl präsentationsbezogener Klassen vermeiden!
Weniger ist mehr!

Verbundene Selektoren

Ein verbundener Selektor (compound selector) besteht aus einem oder mehreren einfachen Selektoren, die ohne Leerzeichen hintereinander geschrieben werden. Ein Beispiel dafür haben wir bereits bei den Attributselektoren gesehen:

button[aria-expanded=true]

verbindet den Typselektor button und den Attributselektor [aria-expanded=true].

Ein verbundener Selektor hat diesen Aufbau.

  • ein Typselektor oder der Universalselektor. Dieser muss am Anfang stehen. Da verbundene Selektoren mit Universalselektor sehr häufig gebraucht werden, darf man ihn auch weglassen. Beispielsweise wird .warning[aria-expanded] vom Browser als *.warning[aria-expanded] interpretiert.
  • optional ein oder mehrere ID-Selektoren. Mehrere? Ja, tatsächlich, das ist aber ein Trick zur Erhöhung der Spezifität und kommt normalerweise nicht vor.
  • optional ein oder mehrere Klassen-Selektoren (auch Pseudoklassen)
  • optional ein oder mehrere Attribut-Selektoren
  • optional ein Pseudoelement. Pseudoelemente müssen am Ende eines verbundenen Selektors stehen.
  • optional ein Sub-Pseudoelement. So etwas kann beispielsweise vorkommen, wenn man einem ::after-Pseudoelement die Eigenschaft display: list-item zuordnet und darin das ::marker-Pseudoelement stylen möchte.
  • Pseudoelemente können durch Pseudoklassen ergänzt werden, beispielsweise ::after:hover.

ID-, Klassen- und Attributselektoren können in beliebiger Reihenfolge notiert werden.


Weitere Beispiele:

input:invalid Ein input-Element, bei dem ein Validierungsfehler aufgetreten ist
.optional[type=search] Ein Element mit der Klasse optional und einem Attribut type="search"
#name:focus Ein Element mit der id "name", das den Fokus besitzt
li::after:hover Ein li-Element, dem ein ::after-Pseudoelement zugeordnet wird, und über diesem Pseudoelement befindet sich der Mauszeiger
li:hover::after Ein li-Element, dass dann ein ::after-Pseudoelement bekommt, wenn sich der Mauszeiger über dem li-Element befindet
Beachte: Ein verbundener Selektor darf keine Leerzeichen enthalten, weil das Leerzeichen den Nachfahren-Kombinator darstellt. Darauf gehen wir noch ein.
Aber: Im Beispiel für IDs mit Sonderzeichen haben wir den Selektor #\31 234 gesehen. Diese Leerstelle ist kein Nachfahren-Kombinator, sondern das Abschlusszeichen einer CSS-Escapesequenz.

Selektor-Listen

Eine Selektor-Liste ist eine komma-separierte Liste von beliebigen Selektoren. Die Selektorliste trifft auf ein Element zu, wenn mindestens einer der darin enthaltenen Selektoren auf das Element zutrifft.

Beispiel
h1 { font-family: sans-serif }
h2 { font-family: sans-serif }
h3 { font-family: sans-serif }
h1, h2, h3 { font-family: sans-serif }

Beide Beispiele setzen für die Überschriften 1., 2. und 3. Ordnung die Eigenschaft font-family auf den Wert sans-serif. Im ersten Beispiel geschieht das einzeln, das zweite Beispiel verwendet eine Selektor-Liste und vermeidet so Redundanz.

fehlertolerante Selektorlisten

Normalerweise gilt: wenn einer der Selektoren in einer Selektor-Liste fehlerhaft ist, gilt die ganze Liste als fehlerhaft und trifft auf kein Element mehr zu. Das kann ärgerlich sein, ist aber nicht mehr zu ändern, ohne ein CSS-Erdbeben auszulösen.

Es gibt aber zwei Ausnahmen von dieser Regel, und zwar die Pseudoklassen :is() und :where(). Sie erwarten eine Selektorliste als Argument, verwerfen bei Fehlern aber nur die fehlerhaften Teile und verwenden die Teile, die korrekt sind.

Beachte: Es gibt weitere Pseudoklassen, die Selektorlisten als Argument erwarten. Diese Selektorlisten verzeihen keine Fehler!

Hintergrund: Die Selektoren-Spezifikation sollte ursprünglich :has() mit einer fehlertoleranten Selektorliste ausstatten. Dabei wurde übersehen, dass die beliebte Bibliothek jQuery bereits eine :has()-Pseudoklasse kannte und ohne Fehlertoleranz interpretierte. Nachdem :has() vom Browser unterstützt wurde, hat jQuery automatisch nicht mehr auf die eigene Sizzle-Engine zurückgegriffen, sondern auf den Browser. Der verhielt sich dann anders und einige jQuery-Programme funktionierten nicht mehr.

Die Frage, was ein Fehler ist, ist dabei nicht so ganz einfach zu beantworten. Ein unbekannter Elementtyp, wie h7 im folgenden Beispiel, ist kein Fehler. Eine unbekannte Pseudoklasse wie z.B. :final-child statt :last-child ist aber einer. Schließt man die Selektorliste in die Pseudoklasse :is() ein, die ihren Inhalt fehlertolerant behandelt, werden immerhin noch a-Elemente, die das erste Kindelement ihres Elternelements sind, blau gefärbt.

Fehlertolerante Selektorliste
/* Kein Fehler, Selektorliste für h1, h2, h3 zu */
h1, h2, h3, h7 { font-family: sans-serif }

/* Fehler, Selektorliste trifft niemals zu */
a:first-child, a:final-child { color: red; }

/* :is() ist fehlertolerant, :final-child wird ignoriert */
:is(a:first-child, a:final-child) { color: blue; }

Kombinatoren

Hinweis: einfache Selektoren lassen sich als verbundene Selektoren auffassen, die nur aus einem Teil bestehen. Wir werden daher ab jetzt die einfachen Selektoren nicht mehr gesondert erwähnen.

Die bisher beschriebenen Selektoren können Elemente auf umfangreiche Weise auswählen, aber eins können sie nicht: Elemente nur in einem bestimmten Kontext suchen. Ein solcher Kontext besteht aus einem Element, das seinerseits mit einem Selektor ausgewählt wird, und der Angabe, wie das Kontext-Element und das Ziel-Element zueinander im DOM angeordnet sind. Für diese Angabe verwendet man Kombinatoren, das sind Sonderzeichen, die zwischen den Selektoren Kontext- und Zielelement notiert werden.

Ein Selektor, der Kombinatoren verwendet, wird komplexer Selektor (complex selector) genannt. Solche Selektoren können Stylesheets übersichtlicher machen und vermeiden die übermäßige Verwendung von Klassen oder IDs.

Der Selektor für das Kontext-Element kann ein komplexer Selektor sein, darf aber keine Pseudoelemente enthalten. Pseudoelemente können nur in dem hinzukombinierten, verbundenen Selektor für das Zielelement genutzt werden.

Man kann den Selektor für das Kontext-Element zusammen mit dem Kombinatorzeichen auch als eine Bedingung auffassen, die erfüllt sein muss, damit der Ziel-Selektor angewendet wird.

Für die nachfolgenden Beschreibungen soll K das Kontextelement bezeichnen und E das Zielelement. Entsprechent meint selK den Selektor für das Kontextelement und selE den Selektor für das Zielelement.

Beachte: Aus Performance-Gründen sind die Kombinatoren so entworfen worden, dass sie mit einem einmaligen Durchlaufen des DOM-Baumes ausgewertet werden können. Das Zielelement in einem komplexen Selektor muss deshalb immer ein Nachfahre oder ein nachfolgendes Geschwisterelement des Kontextelements sein.

Nach langjährigen Diskussionen wurde mittlerweile die Pseudoklasse :has() freigegeben, die auch die umgekehrte Richtung ermöglicht.

Kind-Kombinator

Syntax: selE > selE

Werden zwei Selektoren durch den Kind-Kombinator > (schließende spitze Klammer, Größer-Als-Zeichen) verbunden, z. B. ul > li, so wird das li-Element nur dann angesprochen, wenn es direktes Kindelement eines ul-Elements ist. Das > Zeichen darf dabei beliebig viel Weißraum umgeben sein.

Kind-Kombinator ansehen …
p > em {color: green;}
<h1> Der <em>Kind</em> selektor </h1> <p> <em>Dieses</em> Beispiel demonstriert die Wirkung des <del> <em>Nachbar</em> </del> Kindselektors. </p>

Das em-Element zu Beginn des p-Elements wird grün dargestellt, weil es ein direktes Kind des p-Elements ist. Für die beiden anderen em-Elemente gilt das nicht. Das erste befindet sich in der h1-Überschrift und hat überhaupt kein p-Element in seiner Elternkette. Das em-Element innerhalb des del-Elements ist zwar Nachfahre eines p-Elements, aber kein direktes Kind, sondern sozusagen ein Enkel. Deshalb werden diese beiden em-Elemente nicht grün und erben die Schriftfarbe ihres Elternelements.

Nachfahren-Kombinator

Syntax: selK selE (Leerstelle zwischen selK und selE)

Der Nachfahren-Kombinator besteht lediglich aus Weißraum und ist der Grund, warum innerhalb eines verbundenen Selektors keine Leerstellen zulässig sind. Er stellt die weniger strenge Variante des Kind-Kombinators dar, indem er auch indirekte Kind-Beziehungen (Nachfahren) zulässt.

Beispielsweise wird in nav li das li-Element nur dann angesprochen, wenn es im DOM ein Nachfahre eines nav-Elements ist. Ein Element E ist Nachfahre eines Elements K, wenn man ausgehend von E der Kette der Elternelemente folgt und dabei auf den K stößt.

Stilfestlegung für em-Elemente, die Nachfahrenelemente von p sind. ansehen …
p em {
   color: green;
   padding: border: 1px solid;	
   background-color: #fffbf0;
   font-style: italic; 
}

In diesem Beispiel werden die beiden em-Elemente innerhalb des Absatzes mit grüner Schriftfarbe dargestellt, da es sich bei beiden um Nachfahrenelemente des p-Elements handelt. Das em-Element innerhalb der Überschrift ist kein Nachfahre des p-Elements, es ist deshalb nicht betroffen.

Beachte: Das Leerzeichen (bzw. ein anderes Whitespace-Zeichen) zwischen zwei Selektoren dient nur dann als Kombinator, wenn kein anderer Kombinator vorhanden ist.

Nachbar-Kombinator

Syntax: selK + selE

Werden zwei Selektoren durch den Nachbar-Kombinator + (Pluszzeichen) verbunden, so wird das Element E nur dann angesprochen, wenn es K und E Kind-Elemente des gleichen Elternelements sind und E in der Liste der Kindelemente direkt auf K folgt, also der direkte Nachbar ist.

Beispiel ansehen …
h1 + p { font-weight: bold }
p + p { font-style: italic }
<h1>Nachbarkombinator</h1>
<p>Erster Absatz.</p>
<p>Zweiter Absatz.</p>
<p>Dritter Absatz.</p>
<div>neutrales Element</div>
<p>Vierter Absatz</p>

In diesem Beispiel wird der erste Absatz mit fett formatierter Schrift dargestellt, denn es ist das einzige unmittelbare Nachbar-p-Element von h1.

Für den zweiten und dritten Absatz gilt: Sie sind Nachbar-p-Elemente je eines p-Elements. Sie werden also kursiv dargestellt.

Der vierte Absatz ist ein Nachbar eines neutralen div-Elements und wird nicht gestylt.

Beachte: Die Selektion des vorhergehenden Nachbars ist nur mit Hilfe der :has() Pseudoklasse möglich.

lobotomized owl selector

Der Selektor * + * wird lobotomized owl selector genannt, weil er den „Erfinder“ an eine Eule erinnerte.[3]

Er selektiert alle Elemente, denen auf der selben Ebene ein Geschwisterelement vorausgeht, also alle Elemente, die nicht das erste Kind sind. Für sich allein verwendet ist er viel zu allgemeingültig und würde sogar das <body>-Element selektieren, er sollte deshalb immer zusammen mit einem Kind-Kombinator verwendet werden. Zuweilen findet man auch :not(:first-child).

Genutzt wurde er hauptsächlich für die Formatierung von längeren Texten, wenn man beispielsweise allen Absätzen außer dem ersten Absatz einen margin-top geben möchte. Dafür gibt es heutzutage allerdings bessere Werkzeuge. Zum einen gibt es die Pseudoklasse :nth-child(n+2), zum anderen das Flexbox- oder Grid-Layoutmodell mit der row-gap-Eigenschaft.

Geschwister-Kombinator

Syntax: selK ~ selE

Werden zwei Selektoren durch den Geschwister-Kombinator ~ (Tilde) verbunden, so werden alle Elemente angesprochen, die das gleiche Elternelement wie das Kontext-Element K haben und in der Geschwisterliste auf K folgen – unabhängig davon, ob sich zwischen den Elementen weitere, im Selektor nicht genannte, Elemente befinden.

Beispiel ansehen …
h1 ~ p {font-weight: bold;}
<p>Erster Absatz.</p>
<h1>Der Geschwisterselektor</h1>
<p>Zweiter Absatz.</p>
<hr>
<p>Dritter Absatz.</p>

In diesem Beispiel werden sowohl der zweite als auch der dritte Absatz mit fett formatierter Schrift dargestellt, da beide Elemente auf das h1-Element folgen. Die Trennlinie zwischen den beiden Absätzen verhindert dies nicht. Einzig der erste Absatz wird mit normaler Schrift dargestellt, da er vor dem bedingenden h1-Element steht.

Rückwärtssuche mit :has()

Viele Einsteiger in CSS wundern sich, warum es keine Kombinatoren zur Auswahl eines Elternelements oder vorhergehenden Geschwisterelements gibt. Wie bereits erwähnt, hat das technische Gründe: die CSS-Engines waren auf älteren Geräten dafür einfach zu langsam. jQuery hat vorgemacht, dass es geht, aber damit auch gezeigt, dass ein intensiver Einsatz von :has() einen Browser in die Knie zwingen kann.

Die Pseudoklasse :has() kann einem verbundenen Selektor hinzugefügt werden und enthält einen relativen Selektor. Relativ bedeutet, dass er nicht auf das ganze DOM angewendet wird, sondern nur auf die Kindelemente und nachfolgenden Geschwisterelemente desjenigen Elements, für das :has() ausgewertet wird.

Um ein form Element auszuwählen, in dem sich irgendwo eine Checkbox befindet, kann man

form:has(input[type=checkbox]) {
   ...
}

schreiben. Der Selektor muss damit aber noch nicht zu Ende sein. Möglicherweise möchte ich in dem Form, das eine Checkbox enthält, den Text im Submit-Button weiß machen. Das wäre mit

form:has(input[type=checkbox]) button:is([type=submit],:not([type])) {
   color: white;
}

Der Selektor nutzt :has(), um Forms mit bestimmten Eigenschaften zu finden, und greift darin dann auf button-Elemente mit type=submit oder ohne type-Attribut zu. Dafür wird die Pseudoklasse :is() verwendet, die eine „Oder“-Kombination von Selektoren ermöglicht.

Der Selektor in :has() ist relativ. Das bedeutet: Man muss auch die Art der Relation angeben können. Deshalb beginnt ein relativer Selektor immer mit einem Kombinator. Bei den beiden gezeigten Beispielen war das scheinbar nicht der Fall. Es ist so, dass ein fehlender Kombinator wie Weißraum gedeutet wird, also wie ein Nachfahren-Kombinator. Schauen wir uns an, wie man den Nachbar-Kombinator „umkehren“ kann:

label:has(+ input)::after {
   content: ':';
}

Dieser Selektor trifft auf label-Elemente zu, die unmittelbar von einem input-Element gefolgt werden, und fügt ihnen ein [[CSS/Selektoren/after|::after-Pseudoelement hinzu, um dem Labeltext einen Doppelpunkt hinzuzufügen. Ob das wirklich sinnvoll ist, sei dahingestellt.

Die Kombinatoren > und ~ lassen sich genauso verwenden.

relative Selektoren

An einigen Stellen müssen Selektoren notiert werden, die mit anderen Selektoren kombiniert werden müssen, damit das gewünschte Ergebnis erzieht wird. Ein Beispiel ist die :has()-Pseudoklasse, mit der man abfragen kann, ob ein Element bestimmte andere Elemente enthält. Innerhalb von :has() muss ein Selektor notiert werden, der die zu prüfenden Elemente beschreibt, und dieser Selektor gilt nur in Bezug auf den Selektor, dem :has() zugeordnet ist – er ist relativ zu diesem Selektor.

CSS löst das so, dass der äußere Selektor und der innere Selektor mit einem Kombinator verbunden werden. Dies ist standardmäßig der Nachfahrenselektor (das Leerzeichen). Wenn Sie einen anderen Kombinator verwenden möchten, müssen Sie diesen innerhalb von :has() notieren, was zu ungewohnten Schreibweisen wie :has(> .foo) oder :has(~ ul) führt.

Kurz gesagt: Relative Selektoren sind Selektoren, die mit einem Kombinator beginnen

Weil die Leerstelle den Nachfahrenselektor bildet, folgt daraus, dass :has(div) den relativen Selektor   div enthält.

Selektoren, deren Bezugspunkt das Wurzelelement des Dokuments ist, nennt man dementsprechend absolute Selektoren.

Auch CSS-Schachtelung verwendet relative Selektoren. Sobald der Selektor einer geschachtelten Regel den &-Selektor enthält, setzt CSS dort den Selektor der Elternregel ein und man erhält einen absoluten Selektor. Fehlt das &, handelt es sich um einen relativen Selektor, der sich auf den Selektor der Elternregel bezieht.

Siehe auch


Weblinks

  1. Typselektoren können auch um eine Namensraum-Angabe erweitert werden. Näheres dazu findest du im Artikel zu CSS Namensräumen.
  2. WHATWG HTML Spezifikation: Attribute, bei denen die Schreibung des Wertes nicht beachtet wird
  3. A List Apart: axiomatic css and lobotomized owls