Zum Inhalt
wannacode

Selektoren und die Kaskade

Kurz gesagt: Ein CSS-Selektor wählt die Elemente aus, für die eine Regel gilt, und die Kaskade entscheidet, welche Regel bei einem Konflikt gewinnt: Herkunft, Spezifität und Reihenfolge.

Problem

Der Preis wird nicht rot

Der Shop startet eine Aktion: Der Preis des Brotes soll rot sein. Ein Kollege fügt ganz unten in style.css eine Regel für .price hinzu. Der Preis wird größer und fett, bleibt aber dunkelgrau.

HTML, CSS, JS

Die Konsole ist leer: CSS meldet keine Fehler. Die Regel ist die letzte in der Datei, und sie trifft den Preis, denn Größe und Fettdruck kommen an. Nur die Farbe nicht. Eine andere Regel will für denselben Absatz eine andere Farbe, und der Browser hat sich für sie entschieden.

Die Idee

Regel und Selektor

CSS sagt, wie jedes Element des Baums aussieht. Es sagt das mit Regeln:

.price {
color: #c0392b;
font-size: 20px;
}
  • .price ist der Selektor: Er bestimmt, auf welche Elemente die Regel zutrifft.
  • In den geschweiften Klammern stehen die Deklarationen: Eigenschaft, Doppelpunkt, Wert und ein Semikolon.

Selektoren durchsuchen den Baum, sie sind also wie Fragen an ihn:

  • p (Typ): jedes <p>.
  • .price (Klasse): jedes Element mit class="price". Ein Element kann mehrere Klassen haben: class="price sale".
  • #product (id): das Element mit id="product".
  • [type="email"] (Attribut): die Elemente mit diesem Attribut und diesem Wert, zum Beispiel input[type="email"].
  • article p (Nachfahre, mit Leerzeichen): ein <p> irgendwo in einem <article>, in beliebiger Tiefe.
  • nav > a (Kind): ein <a>, das direktes Kind von <nav> ist.
  • .price.sale (ohne Leerzeichen): ein Element mit beiden Klassen.
  • h1, h2 (Liste): Die Regel gilt für beide.

Stile schreibt man meistens mit Klassen. Ein Typ trifft jeden Absatz der Website, und eine id ist für ein einziges Element. Eine Klasse steht genau dort, wo du sie brauchst, und hängt nicht davon ab, wie der Baum aufgebaut ist.

Probier es aus

Triff genau diese

Nimm die Unterstreichung nur bei den Links im Menü weg (der Link unten bleibt unterstrichen) und mach beide Preise fett, ohne die Beschreibungen fett zu machen. Die Eigenschaften sind text-decoration: none und font-weight: 700.

HTML, CSS, JS

Die Idee

Die Kaskade

Den Preis vom Anfang treffen zwei Regeln, und beide setzen color. Der Browser muss eine wählen. Diese Auswahlregel heißt Kaskade. Sie vergleicht auf drei Ebenen und hört bei der ersten auf, die entscheidet:

  1. Herkunft. Der Browser hat eigene Stile: Deshalb ist <h1> groß und ein Link blau und unterstrichen. Dein CSS schlägt sie.
  2. Spezifität. Wie genau der Selektor ist. Es sind drei Zahlen: wie viele ids, wie viele Klassen, wie viele Typen. p ist 0,0,1, .price ist 0,1,0, #product p ist 1,0,1. Attribute ([type="email"]) und Zustände (:hover) zählen wie Klassen. Die Zahlen werden Spalte für Spalte von links verglichen. Sobald eine Spalte abweicht, ist es entschieden: 1,0,1 schlägt 0,1,0.
  3. Reihenfolge. Bei gleicher Spezifität gewinnt die Regel, die später im Code steht.

Die Kaskade entscheidet jede Eigenschaft einzeln. Deshalb kommen font-size und font-weight von .price an: Nichts anderes konkurriert um sie. Bei color konkurriert etwas, und es ist stärker.

Es gibt auch !important: color: #c0392b !important schlägt jede normale Deklaration, egal welche Spezifität. Es funktioniert, aber danach braucht jede Änderung der Farbe ein neues !important. Es ist also ein Zeichen dafür, dass irgendwo ein Selektor zu stark ist, und keine Lösung.

Sieh es dir an

Sieh zu, wie der Browser wählt

Vier Regeln und ein Element. Achte darauf, wie der Browser color und font-size getrennt entscheidet.

/* <article id="product">
<p class="price sale">1,80 €</p>
</article> */
p { color: #555; font-size: 16px; }
.price { color: #c0392b; font-size: 20px; }
#product p { color: #222; }
.sale { font-size: 24px; }
Schritt für Schritt, in Worten
  1. Ein Element: ein <p> mit den Klassen price und sale, in <article id="product">. Alle vier Selektoren treffen es. Zwei der Regeln wollen color setzen und drei font-size.
  2. Die Spezifität eines Selektors besteht aus drei Zahlen: wie viele ids, wie viele Klassen, wie viele Typen. #product p hat eine id und einen Typ: 1,0,1.
  3. color: Drei Regeln setzen es. Der Browser vergleicht die erste Spalte: 1 schlägt 0, und weiter schaut er nicht. #product p gewinnt, obwohl .price danach kommt.
  4. font-size: wieder drei Regeln. Die id-Spalte ist gleich (0). In der Klassenspalte fällt p mit 0 heraus. .price und .sale sind in allen drei Spalten gleich.
  5. Gleiche Spezifität: Die Regel, die später im Code steht, gewinnt. .sale steht in Zeile 7, nach .price, deshalb ist font-size 24px.
  6. Jede Eigenschaft hat ihren eigenen Gewinner: color von #product p, font-size von .sale. Die Regel .price trifft das Element und verliert trotzdem in beiden.

Hier ist derselbe Code im Browser. Der Preis ist dunkelgrau und 24px groß, wie in der Szene. Tausch .price und .sale: Die Größe ändert sich, die Farbe nicht. Öffne die Entwicklertools (F12), wähl den Preis aus und sieh dir das Panel Stile an: Die unterlegenen Deklarationen sind durchgestrichen.

HTML, CSS, JS

Die Idee

Vererbung

Manche Eigenschaften gehen vom Elternelement auf die Kinder über. Wenn ein Element dafür keine eigene Regel hat, übernimmt es den Wert seines Elternelements. Das ist Vererbung.

  • Die Eigenschaften des Textes werden vererbt: color, font-family, font-size, font-weight, line-height, text-align.
  • Die Eigenschaften der Box nicht: border, padding, margin, background, width. Ein Rahmen um die Karte heißt nicht, dass jeder Absatz darin einen Rahmen hat.

Ein geerbter Wert ist der schwächste. Jede Regel, die das Element direkt trifft, schlägt ihn, sogar p mit 0,0,1. Buttons und Felder bekommen ihre eigene Schrift und Farbe vom Browser, deshalb erben sie nicht. inherit verlangt die Vererbung ausdrücklich: button { font-family: inherit; }.

HTML, CSS, JS

Der Text der Karte ist grün und in Georgia, aber der Rahmen ist nur um die Karte. Der Button hat die Schrift wegen inherit übernommen, und seine Farbe blieb schwarz: Für color gibt es keine solche Regel.

Probier es aus

Repariere den Preis

Mach den Preis rot (#c0392b), ohne !important. Die Beschreibung muss dunkelgrau (#222) bleiben.

HTML, CSS, JS

Probier es aus

Finde den Fehler

Der Preis hat die Klassen price und sale, ist aber nicht rot. Warum?

Wähle die Zeile mit dem Fehler.

Probier es aus

Ergänze

Das Menü hat Links und eine verschachtelte Liste mit weiteren Links. Nur die Links, die direkte Kinder von <nav> sind, sollen keine Unterstreichung haben.

nav  a {
  text-decoration: none;
}
Genauer, für Neugierige

Herkunft. Es gibt drei Quellen: den Browser, den Nutzer (Einstellungen und Erweiterungen) und den Autor, also dich. Bei normalen Deklarationen schlägt der Autor den Nutzer, und der Nutzer schlägt den Browser. Mit !important kehrt sich die Reihenfolge um: Das !important des Nutzers schlägt deins. So kann ein Mensch mit schwachen Augen auf jeder Website eine größere Schrift erzwingen.

style="…". Ein Stil im Attribut des Elements schlägt jeden Selektor in der Datei. Er ist also auch eine Falle, wie !important.

Spalten laufen nicht über. 0,11,0 ist nicht 1,1,0. Elf Klassen schlagen eine id nicht: Der Vergleich endet in der ersten Spalte.

Was nicht zählt. * ist 0,0,0. Kombinatoren (Leerzeichen, >, +, ~) fügen nichts hinzu. Pseudoelemente (::before) zählen wie Typen.

:is(), :not() und :where(). :is() und :not() übernehmen die Spezifität ihres stärksten Arguments. :where() ist immer 0,0,0: praktisch für Standardstile, die jede Regel überschreibt.

Ebenen. @layer ordnet ganze Gruppen von Regeln, und die Ebene entscheidet vor der Spezifität. Große Stilbibliotheken nutzen es, damit sie sich nicht mit deinem CSS streiten.

Die Schlüsselwörter. inherit übernimmt den Wert des Elternelements. initial ist der Startwert der Eigenschaft aus dem Standard (bei display ist es inline). unset ist inherit bei vererbten Eigenschaften und initial bei den anderen. revert bringt den Stil des Browsers zurück.

Übung

Die Aktion im Katalog

Der Katalog hat drei Produkte, und die Milch ist im Angebot (die Klasse sale an ihrer Karte). Aller Text im Katalog ist #222, und die Preise sind fett. Der Preis des Produkts im Angebot ist rot (#c0392b), und der alte Preis darin ist grau (#777). Das Label −20% hat weißen Text (#fff) auf rotem Hintergrund (#c0392b). Die anderen Preise bleiben #222. Benutz kein !important.

HTML, CSS, JS

Test

Teste dich

1. Welche Spezifität hat #cart .item a?
2. Zuerst kommt article p { color: gray; }, dann .price { color: red; }. Welche Farbe hat <p class="price"> in einem <article>?
3. .card { color: green; border: 1px solid; }. Was bekommt ein <p> in der Karte, wenn keine andere Regel zutrifft?
4. Warum ist !important im Code ein schlechtes Zeichen?
5. Warum schreibt man Stile meistens mit Klassen und nicht mit ids?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·