CSS Kontext-Selektoren

Nachfahren-Selektoren und Nachbar-Selektoren wählen Elemente anhand ihrer Position zu anderen Elementen aus – aus dem Kontext oder der Kombination von Elementen in der HTML-Struktur. Kontext-Selektoren sind also abhängig von der Struktur, in der sie auftreten: von ihren Nachbarn, Vorfahren und Nachfahren.

CSS context selector – Nachbar-Elemente

Nachfolger – Nachbar-Selektoren

Jetzt wird's kleinlich in der Nachbarschaft:

  • Ein Nachfahren-Selektor oder Descendant Selector filtert Elemente unterhalb bestimmter Elemente.
  • Ein Nachbar-Selektor oder Adjacent Selector filtert Elemente, die aufeinander folgen und auf derselben Ebene liegen.
Kontext ───┐  ┌── Selektiertes Element
           │  │
           ▼  ▼
          div p { … }
           ▲  │
           └──┘
Nachfahre (Descendant): Filtert p-Elemente, die innerhalb eines div-Elements liegen.
┌── Kontext ──┐      ┌── Selektiertes Element
│             │      │
▼             ▼      ▼
main ul.hangout:last-child { … }
▲                    │
└────────────────────┘

Nachfahre (Descendant): Filtert das jeweils letzte Element der Klasse .hangout, das innerhalb eines ul-Elements liegt, das wiederum unterhalb des main-Elements liegt.

Wir schreiben CSS-Regeln von links nach rechts, aber die Browser interpretieren CSS-Regeln von rechts nach links.

E F
Nachfahren-Selektor | Descendant
a img { border: 4 px solid orange }
Alle img-Tags, die innerhalb eines a-Tags liegen, auch in zweiter oder dritter Ebene. Zwischen dem Eltern-Selektor und dem Kind-Selektor sitzt ein Leerzeichen.
E > F
Kind-Selektor | Child
div>table { border: thin dashed green; }
Alle table-Elemente, die direkt innerhalb eines div-Elements liegen. Selektoren, die durch ein >-, +- oder ~-Symbole voneinander getrennt sind, werden auch als »Kombination« bezeichnet.
E + F
Direkter Nachbar-Selektor | Adjacent
h5 + p { font-weight: bold }
Das p-Element, das direkt auf eine Überschrift h5 folgt.
E ~ F
Indirekter oder allgemeiner Nachbar-Selektor
h5 ~ p { color: dimgray }
Alle p-Elemente, die der Überschrift h5 folgen und auf derselben Ebene innerhalb eines Eltern-Elements liegen ().

Kontext-Selektoren wirken nicht nur auf CSS, sondern filtern mit querySelector und querySelectorAll Elemente mit Javascript.

Nachfahren-Selektor (Descendant)

CSS descendant selector
CSS descendant selector
<div>
	<h2> … </h2>
	<p> … </p>
	<ul>
		<li> … </li>
		<li><p> … </p></li>
		<li></li>
	</ul>
	<p> … </p>
</div>
div p { color: white; background-color: red; }

Die Regel spricht alle p-Elemente an, die innerhalb von div-Elementen liegen.

Die Umkehrung wäre der has()-Selektor, der ein Eltern-Element nur dann anspricht, wenn es bestimmte Kind-Elemente enthalten würde, z.B. ein figure-Element nur, wenn ein figcation-Element unterhalb von figure liegt: figure:has(figcaption).

Kind-Selektor (Child)

CSS child selector
CSS child selector
div > p { color: white; background-color: red; }

trifft nur auf p-Elemente zu, die direkt unterhalb des div-Elements liegen.

Der Kind-Selektor birgt allerdings eine Falle: Bei Eigenschaften, die nicht vererbt werden, funktioniert der Kind-Selektor wie erwartet, aber bei erblichen (inherit) Eigenschaften wirken sich Eigenschaften auf alle Abkömmlinge aus.

  • Ein direktes Kind von ul
  • Ein direktes Kind von ul
    • Kein direktes Kind vom obersten ul
  • Ein direktes Kind von ul
    • Kein direktes Kind vom obersten ul
  • Ein direktes Kind von ul
ul.demolist > li { 
	text-transform: uppercase; font-size: 1.2em; opacity: 0.5; text-align: right; border-bottom: 2px solid red; margin-bottom: 1.5em; }

font-size und und text-transform sind erbliche Eigenschaft, darum wirken sie auf alle li-Elemente, nicht nur auf direkte Kind-Elemente.

border und margin sind nicht erblich und wirken nur auf direkte Kind-Elemente des oberen ul-Elements. Vererbung – Inheritance – mit Ecken und Kanten …

Kombination mit class

Auch diese Kontext-Selektoren können z.B. durch Klassen- oder id-Selektoren noch weiter eingeschränkt werden.

div#nurHier p.content { color: white; background-color: green; width: 500px; }

Nur Inhalte von p-Elementen mit dem Attribut class="content", die innerhalb des div-Elements mit dem id-Attribut id="nurHier" liegen, werden den aufgeführten Regeln unterworfen.

CSS Vorgänger-Selektoren

Die CSS-Kontext-Selektoren greifen auf Elemente derselben Ebene zurück, die einem bestimmten Element folgen (Nachfolger), entweder direkt (E + F) oder indirekt (E ~ F). CSS-Selektoren, die ein vorangehendes Element (Vorgänger) erreichen, gibt es immer noch nicht. Um z.B. das H2-Element eines p-Elements auf derselben Ebene zu treffen, muss Javascript mit previousElementSibling einschreiten. Allem Anschein nach ist CSS richtungsgebunden, um Webseiten vor einem erneuten Aufbau und unendlichen Schleifen zu schützen.

Ein Vorfahren-Element, z.B. das umfassende div class="container" über einem Element, würde über den has-Selektor angesprochen, der zurzeit aber nur von Safari unterstützt wird.

Parent- oder Eltern-Selektoren

Was lange Zeit fehlte, war ein Eltern-Selektor oder Parent Selector – die Option, das Eltern-Element oder Vorgänger-Elemente eines Elements anzusprechen. Die Gefahr von unbeabsichtigten Überschreibungen ist bei einem rückwärts (vom Kind auf den Vorfahren) gerichteten Selektor groß, und sogar unendliche Schleifen könnten durch einen CSS Vorfahren- oder Parent-Selector entstehen.

Der :has()-Selektor füllt jetzt die Lücke: Er trifft auf alle Elemente zu, die mindestens ein bestimmtes Element enthalten. In diesem Beispiel würden figure-Elemente gewählt, die ein figcaption-Element enthalten:

figure:has(figcaption) {
	border: 2px solid green;
}

Kontext-Selektoren und Performance

Diese Selektoren sind zwar sehr mächtig und zudem im Stylesheet gut lesbar, sie kosten aber auch Performance vom Browser.

Wir lesen einen Kontext-Selektor wie hier von links nach rechts

#content article .main p span { color: blue; }

…

<div id="content">
   <article>
      <div class="main">
         <p>Wahrscheinlich waren es <span>Stunden</span> über 
            Stunden, die …</p>
      </div>
   </article>
</div>

Wenn in #content ein article-Tag steht und darunter ein Element mit der Klasse .main in dem ein p liegt und darin ein span – dann rendere den Inhalt Blau.

Der Browser löst die Eigenschaft aber von rechts nach links auf: Der Browser sucht erst alle span-Elemente, dann filtert er die span-Elemente, die in p-Tags liegen … usw.

So elegant Kontext-Selektoren auch sind – für schnelle Reaktionszeiten sollten sie sparsam und bewußt verwendet werden.

div p { … } Selektiertes Element Kontext main ul .hangout:last-child { … } Kontext Selektiertes Element
Suchen auf mediaevent.de