Zum Inhalt springen

Selektoren im Detail

Für den Browser ist ein HTML-Dokument kein Text, sondern ein Baum aus verschachtelten Elementen: das Document Object Model (DOM). Selektoren wählen Knoten in genau diesem Baum aus.

Dafür ein paar Fachbegriffe, die in CSS-Doku und Fehlermeldungen immer wieder auftauchen:

  • Element / Node - ein einzelner Knoten im Baum (ein Tag oder ein Text)
  • Eltern-Element - der Knoten eine Ebene darüber
  • Kinder - die Knoten eine Ebene darunter
  • Vorfahren - alle Knoten darüber, beliebig viele Ebenen
  • Nachkommen - alle Knoten darunter, beliebig viele Ebenen

Der Stern * wählt alle Elemente im Dokument aus:

* {
box-sizing: border-box;
}

Das kennt ihr schon aus dem Box-Modell-Abschnitt. Genau darum wird der Universal-Selektor in der Praxis fast nur für diesen einen Reset verwendet, nicht für echtes Styling. Zu allgemeine Regeln treffen zu viel und sind schwer vorhersehbar.

Eine id muss im Dokument einzigartig sein. Deshalb ist sie nicht nur für CSS nützlich, sondern auch als Textmarke in der URL aufrufbar:

<body>
<nav id="menu">Navigation...</nav>
<footer id="copyright">© ...</footer>
</body>

Angenommen, diese Seite ist unter https://example.com/seite.html erreichbar. Dann springt der Browser bei folgenden URLs direkt zur jeweiligen Stelle:

  • https://example.com/seite.html#menu
  • https://example.com/seite.html#copyright

Der CSS-Selektor verwendet dieselbe Raute (#):

#menu { background-color: yellow; }

Nachfahren nochmal genauer: der Descendant Combinator

Abschnitt betitelt „Nachfahren nochmal genauer: der Descendant Combinator“

Ein Leerzeichen zwischen zwei Selektoren wählt alle Elemente aus, die irgendwo verschachtelt in einem anderen Element liegen. Egal wie tief:

<section>
<a href="#">direkter Link</a>
<p>Text mit <a href="#">verschachteltem Link</a></p>
</section>
section a {
color: darkorange;
}

→ Beide a-Tags werden getroffen, auch der, der zwei Ebenen tief in einem p steckt.

Browser unterscheiden bei <a>-Tags automatisch zwischen mehreren Zuständen - dafür gibt es eigene Pseudo-Klassen:

a:link { color: blue; } /* noch nicht besucht */
a:visited { color: purple; } /* schon einmal besucht */
a:hover { color: red; } /* Maus ist gerade drüber */
a:active { color: orange; } /* wird gerade angeklickt */
Pseudo-KlasseWann aktiv?
:linkLink wurde noch nicht besucht
:visitedLink wurde schon einmal besucht
:hoverMaus befindet sich über dem Element (auf Touch-Geräten wirkungslos)
:activeElement wird gerade geklickt/getippt - nur für einen kurzen Moment

:hover ist nicht auf Links beschränkt. Die Pseudo-Klasse wird an einen beliebigen Selektor angehängt und gilt, solange sich der Mauszeiger über dem Element befindet. Sobald die Maus das Element verlässt, gelten wieder die normalen Styles:

.btn {
background-color: #2563eb;
}
.btn:hover {
background-color: #1d4ed8; /* etwas dunkler, solange die Maus drüber ist */
}
.card:hover {
border-color: #2563eb; /* ganze Karte hervorheben */
}
tr:hover {
background-color: #f3f4f6; /* Tabellenzeile unter dem Mauszeiger markieren */
}
  • In der :hover-Regel stehen nur die Eigenschaften, die sich ändern sollen. Alles andere wird von der normalen Regel übernommen
  • :hover gilt auch, wenn die Maus über einem Kind-Element ist: Fährt man über das <h2> in einer .card, ist trotzdem .card:hover aktiv
  • Hover-Effekte signalisieren „hier kann man etwas tun“. Sie gehören deshalb vor allem auf klickbare Elemente

Neben :hover gibt es :focus - aktiv, wenn ein Element per Tastatur (Tab-Taste) oder Klick den Eingabefokus hat:

button:focus,
a:focus {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
  • Nicht nur Links/Buttons können fokussiert werden - auch Formularfelder (input, textarea, select)
  • Der Browser zeigt standardmäßig einen outline-Rahmen bei Fokus - das ist für Tastatur-Nutzer*innen die einzige visuelle Rückmeldung, welches Element gerade “aktiv” ist

Der Descendant Combinator (Leerzeichen) trifft beliebig tief verschachtelte Nachkommen. Der Child Combinator > ist strenger. Er trifft nur direkte Kinder:

<ul class="intro">
<li><a href="#">direktes Kind</a></li>
<li><span><a href="#">zwei Ebenen tief</a></span></li>
</ul>
.intro > a { color: yellow; } /* trifft KEIN a - die a-Tags sind Enkel, nicht Kinder */
li > a { color: yellow; } /* trifft nur das erste a, direktes Kind von li */

Document Object Model und Selektor

Kombinierte Selektoren: das Komma hat die geringste Präzedenz

Abschnitt betitelt „Kombinierte Selektoren: das Komma hat die geringste Präzedenz“
p, section a { color: yellow; }

Dieser Selektor bedeutet: entweder ein p-Element, oder ein a innerhalb einer section. Nicht: “ein Link, der entweder in einem p oder in einer section liegt”.

Document Object Model und Selektor

NameMusterBeschreibung
Universal-Selektor*Trifft jedes Element
Type-SelektorETrifft jedes E-Element
GruppierungE, F, GTrifft E- oder F- oder G-Elemente
Descendant CombinatorE FTrifft jedes F, das Nachkomme eines E ist
Child CombinatorE > FTrifft jedes F, das direktes Kind eines E ist
Klassen-SelektorE.klasseTrifft jedes E mit class="klasse"
ID-SelektorE#idTrifft das E mit id="id"
Link-Pseudo-Klassen:link :visitedNoch nicht besuchter / bereits besuchter Link
Dynamische Pseudo-Klassen:hover :active :focusTrifft während bestimmter Interaktionen (Maus drüber, wird geklickt, hat Fokus)
:target-Pseudo-Klasse:targetTrifft das Element, dessen ID mit dem #anker in der URL übereinstimmt
:root-Pseudo-Klasse:rootTrifft die Wurzel des DOM, immer <html>

Weitere Selektoren (Attribut-Selektoren, :nth-child(), Pseudo-Elemente, :has()) folgen im Layout-Kapitel.