CSS Pseudo-Classes
Pseudo-Classes stylen Elemente basierend auf ihrem Zustand oder Position. Mit einem Doppelpunkt : gekennzeichnet.
Was sind Pseudo-Classes?
Pseudo-Classes selektieren Elemente in einem bestimmten Zustand:
selector:pseudo-class {
property: value;
}
/* Beispiel */
a:hover {
color: red;
}Kein Extra-Element im HTML nötig!
Interaktions-Pseudo-Classes
:hover - Maus darüber
/* Bei Maus-Hover */
a:hover {
color: red;
text-decoration: underline;
}
button:hover {
background-color: #0056b3;
transform: translateY(-2px);
}
.card:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}Häufigster Use Case: Feedback bei Interaktion
:active - Beim Klicken
button:active {
transform: scale(0.95);
background-color: #004085;
}
a:active {
color: darkred;
}Moment des Klicks (Mausbutton gedrückt)
:focus - Fokus (Tastatur)
/* Wenn fokussiert (Tab-Taste) */
input:focus {
outline: 2px solid #007bff;
border-color: #007bff;
}
button:focus {
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
/* Focus sichtbar machen */
a:focus {
outline: 2px solid #007bff;
outline-offset: 2px;
}Wichtig für Accessibility! Tastatur-User brauchen Fokus-Indicator.
:focus-visible - Smarter Focus
/* NUR bei Tastatur-Focus, NICHT bei Maus-Click */
button:focus-visible {
outline: 2px solid #007bff;
}
/* Entfernt Outline bei Maus-Click */
button:focus:not(:focus-visible) {
outline: none;
}Modern & empfohlen: Zeigt Focus nur wenn nötig (Tastatur).
:focus-within - Fokus in Kind
/* Wenn irgendein Kind fokussiert ist */
.form-group:focus-within {
background-color: #f0f8ff;
border-color: #007bff;
}
.search-container:focus-within {
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}Use Case: Form-Container highlighten wenn Input fokussiert.
Link-Pseudo-Classes
Spezielle States für Links:
/* Unbesuchter Link */
a:link {
color: #007bff;
}
/* Besuchter Link */
a:visited {
color: #6c757d;
}
/* Bei Hover */
a:hover {
color: #0056b3;
text-decoration: underline;
}
/* Beim Klicken */
a:active {
color: #004085;
}
/* WICHTIG: Reihenfolge! */
/* LVHA = Link, Visited, Hover, Active */Merkhilfe: LVHA (Love Hate)
Positions-Pseudo-Classes
:first-child / :last-child
/* Erstes Kind */
li:first-child {
font-weight: bold;
}
/* Letztes Kind */
li:last-child {
border-bottom: none;
}
/* Praktisch: Spacing */
.card:last-child {
margin-bottom: 0; /* Kein Margin beim letzten */
}:first-of-type / :last-of-type
/* Erstes p-Element */
p:first-of-type {
font-size: 1.25rem;
}
/* Letztes p-Element */
p:last-of-type {
margin-bottom: 0;
}
/* Unterschied zu :first-child: */
/* :first-of-type ignoriert andere Element-Typen */:nth-child() - N-tes Kind
Mächtigster Positions-Selector:
/* Jedes 2. Element (gerade) */
li:nth-child(even) {
background-color: #f5f5f5;
}
/* Jedes 2. Element (ungerade) */
li:nth-child(odd) {
background-color: white;
}
/* Spezifisches Element (3. Kind) */
li:nth-child(3) {
color: red;
}
/* Jedes 3. Element */
li:nth-child(3n) {
font-weight: bold;
}
/* Jedes 3. Element, ab dem 2. */
li:nth-child(3n+2) {
color: blue;
}
/* Erste 3 Elemente */
li:nth-child(-n+3) {
font-size: 1.2rem;
}
/* Alle außer erste 3 */
li:nth-child(n+4) {
opacity: 0.7;
}Formeln:
even=2n(2, 4, 6, ...)odd=2n+1(1, 3, 5, ...)3n= (3, 6, 9, ...)3n+1= (1, 4, 7, ...)-n+3= (3, 2, 1) - erste 3n+4= (4, 5, 6, ...) - ab 4.
:nth-of-type()
/* Jedes 2. p-Element */
p:nth-of-type(2n) {
color: gray;
}
/* 3. p-Element */
p:nth-of-type(3) {
font-weight: bold;
}:only-child / :only-of-type
/* Wenn einziges Kind */
li:only-child {
list-style: none;
}
/* Wenn einziges p-Element */
p:only-of-type {
text-align: center;
}Form-Pseudo-Classes
:checked - Checkbox/Radio
/* Checked Checkbox/Radio */
input[type="checkbox"]:checked {
background-color: #007bff;
}
/* Custom Checkbox Style */
input[type="checkbox"]:checked + label {
font-weight: bold;
color: #007bff;
}
/* Radio Button */
input[type="radio"]:checked + label::before {
background-color: #007bff;
}:disabled - Deaktiviert
input:disabled {
background-color: #e9ecef;
cursor: not-allowed;
opacity: 0.6;
}
button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
button:disabled:hover {
background-color: #6c757d; /* Kein Hover-Effekt */
}:enabled - Aktiviert
input:enabled {
border-color: #ced4da;
}
input:enabled:focus {
border-color: #007bff;
}:required / :optional
/* Pflichtfelder */
input:required {
border-left: 3px solid #dc3545;
}
/* Optionale Felder */
input:optional {
border-left: 3px solid #6c757d;
}:valid / :invalid
/* Gültige Eingabe */
input:valid {
border-color: #28a745;
}
/* Ungültige Eingabe */
input:invalid {
border-color: #dc3545;
}
/* Nur bei Interaktion zeigen */
input:not(:placeholder-shown):invalid {
border-color: #dc3545;
}:placeholder-shown
/* Wenn Placeholder sichtbar (leer) */
input:placeholder-shown {
border-color: #ced4da;
}
/* Wenn NICHT leer */
input:not(:placeholder-shown) {
border-color: #28a745;
}:in-range / :out-of-range
/* Für number/range inputs */
input[type="number"]:in-range {
border-color: #28a745;
}
input[type="number"]:out-of-range {
border-color: #dc3545;
}:not() - Negation
Alles AUSSER:
/* Alle li außer letztes */
li:not(:last-child) {
border-bottom: 1px solid #dee2e6;
}
/* Alle Buttons außer disabled */
button:not(:disabled) {
cursor: pointer;
}
button:not(:disabled):hover {
background-color: #0056b3;
}
/* Mehrere Ausnahmen */
input:not([type="submit"]):not([type="button"]) {
width: 100%;
}
/* Komplex */
div:not(.special):not(#unique) {
color: gray;
}:is() und :where() - Gruppierung
Moderne Selektoren für weniger Code:
/* Alte Schreibweise */
h1:hover,
h2:hover,
h3:hover {
color: red;
}
/* Mit :is() (gleicher Effekt) */
:is(h1, h2, h3):hover {
color: red;
}
/* Komplex */
:is(.card, .panel) :is(h1, h2) {
margin-bottom: 1rem;
}:where() = gleich wie :is(), aber 0 Spezifität:
/* :where() hat keine Spezifität */
:where(h1, h2, h3) {
color: blue;
}
h1 {
color: red; /* Gewinnt, weil :where() = 0 */
}:empty - Leere Elemente
/* Leere divs verstecken */
div:empty {
display: none;
}
/* Oder Nachricht anzeigen */
.list:empty::after {
content: "Keine Einträge vorhanden";
color: #6c757d;
}:target - URL-Fragment
/* Wenn Element über URL angesprungen */
/* URL: example.com#section1 */
#section1:target {
background-color: #fff3cd;
border-left: 4px solid #ffc107;
}
/* Smooth Scroll zu Target */
:target {
scroll-margin-top: 80px; /* Offset für Fixed Header */
}Praktische Beispiele
Beispiel 1: Zebra-Stripes (Tabelle)
table tbody tr:nth-child(odd) {
background-color: #f8f9fa;
}
table tbody tr:nth-child(even) {
background-color: white;
}
table tbody tr:hover {
background-color: #e9ecef;
}Beispiel 2: Card Grid ohne letzten Margin
.card {
margin-bottom: 20px;
}
.card:last-child {
margin-bottom: 0;
}
/* Oder mit :not() */
.card:not(:last-child) {
margin-bottom: 20px;
}Beispiel 3: Custom Checkbox
/* HTML */
<input type="checkbox" id="check1">
<label for="check1">Akzeptieren</label>
/* CSS */
input[type="checkbox"] {
appearance: none;
width: 20px;
height: 20px;
border: 2px solid #ced4da;
border-radius: 4px;
cursor: pointer;
}
input[type="checkbox"]:checked {
background-color: #007bff;
border-color: #007bff;
}
input[type="checkbox"]:checked::after {
content: '✓';
color: white;
display: block;
text-align: center;
}
input[type="checkbox"]:focus {
outline: 2px solid #007bff;
outline-offset: 2px;
}Beispiel 4: Form Validation
input {
border: 2px solid #ced4da;
padding: 10px;
transition: border-color 0.3s;
}
/* Valid */
input:valid:not(:placeholder-shown) {
border-color: #28a745;
}
input:valid:not(:placeholder-shown) + .icon {
color: #28a745;
}
/* Invalid */
input:invalid:not(:placeholder-shown) {
border-color: #dc3545;
}
input:invalid:not(:placeholder-shown) + .error {
display: block;
color: #dc3545;
}
/* Focus */
input:focus {
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}Beispiel 5: Navigation Active State
.nav-link {
color: #6c757d;
text-decoration: none;
padding: 10px 15px;
transition: color 0.3s;
}
.nav-link:hover {
color: #007bff;
}
.nav-link:focus-visible {
outline: 2px solid #007bff;
outline-offset: 2px;
}
/* Active Link (mit Klasse oder :target) */
.nav-link.active,
.nav-link:target {
color: #007bff;
font-weight: 600;
border-bottom: 2px solid #007bff;
}Spezifität mit Pseudo-Classes
Pseudo-Classes erhöhen Spezifität:
/* Element = 1 Punkt */
a {
color: blue;
}
/* Element + Pseudo-Class = 11 Punkte */
a:hover {
color: red; /* Gewinnt! */
}
/* Klasse + Pseudo-Class = 20 Punkte */
.link:hover {
color: green; /* Gewinnt! */
}Best Practices
✅ DO:
- :hover für visuelle Feedback
- :focus für Keyboard Accessibility
- :focus-visible statt :focus (modern)
- :nth-child für Patterns (Zebra-Stripes)
- :not() für Ausnahmen
- :checked für Custom Checkboxes
- Transitions für smooth State-Changes
❌ DON'T:
- Nicht :hover ohne :focus (Accessibility!)
- Nicht outline entfernen ohne Alternative
- Nicht zu spezifisch (einfach halten)
- Nicht :active ignorieren (Click-Feedback)
- Nicht :nth-child übertreiben (Lesbarkeit!)
📝 Quiz
Was ist der Unterschied zwischen :first-child und :first-of-type?
📝 Quiz
Wofür ist :focus-visible gut?
Tipps & Tricks
:is() für kompakte Selektoren
Vermeide Wiederholungen mit :is():
/* Statt */
h1:hover, h2:hover, h3:hover { color: blue; }
/* Nutze */
:is(h1, h2, h3):hover { color: blue; }
/* Auch verschachtelt */
:is(.card, .panel) :is(h1, h2) {
margin-bottom: 1rem;
}
Spart Zeilen und verbessert Lesbarkeit!
Form-Validierung nur nach Interaktion
Zeige Fehler erst nach User-Input:
/* Nicht sofort rot beim Laden */
input:not(:placeholder-shown):invalid {
border-color: #dc3545;
}
/* Oder nach Focus */
input:invalid:focus {
border-color: #dc3545;
}
/* Success nach gültigem Input */
input:not(:placeholder-shown):valid {
border-color: #28a745;
}
:has() für Parent Selektoren (Modern!)
Style Parent basierend auf Kindern:
/* Card mit Bild bekommt anderen Style */
.card:has(img) {
display: grid;
grid-template-columns: 1fr 2fr;
}
/* Form mit Fehler bekommt roten Border */
form:has(input:invalid) {
border: 2px solid #dc3545;
}
/* Navigation wenn Link active ist */
nav:has(a.active) {
background: #f0f0f0;
}
Game Changer für Parent-Styling!
Kombiniere Pseudo-Classes für Smart Spacing
Nutze :not(:last-child) für automatische Abstände:
/* Alle li außer letztes bekommen Border */
li:not(:last-child) {
border-bottom: 1px solid #eee;
}
/* Alle Sections außer erste bekommen Margin */
section:not(:first-of-type) {
margin-top: 3rem;
}
/* Cards mit Gap ohne letzten Margin */
.card:not(:last-child) {
margin-bottom: 20px;
}
Übungsaufgaben
Aufgabe 1: Button States
Erstelle einen Button mit:
- :hover (Farbe + translateY)
- :active (scale)
- :focus-visible (Outline)
- :disabled (grau + cursor)
Aufgabe 2: Form Validation
Style ein Input-Feld:
- :focus (blauer Border)
- :valid (grüner Border)
- :invalid (roter Border)
- Nur nach Eingabe zeigen
Aufgabe 3: Zebra Table
Erstelle eine Tabelle mit:
- :nth-child(odd) graue Rows
- :hover hellblau
- :first-child fett
- :last-child kein Border
Nächste Schritte
Du kennst jetzt:
- ✅ Interaktions-Pseudo-Classes (:hover, :active, :focus)
- ✅ Positions-Pseudo-Classes (:first-child, :nth-child)
- ✅ Form-Pseudo-Classes (:checked, :valid, :disabled)
- ✅ :not(), :is(), :where()
- ✅ Praktische Anwendungen
Als Nächstes lernst du:
- Pseudo-Elements (::before, ::after)
- Advanced Selectors
- CSS Architecture
Weiter so! 🚀
Gut gemacht! 🎉
Du hast "CSS Pseudo-Classes - :hover, :focus, :nth-child & mehr" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
CSS Transitions & Animations - Bewegung ins Design bringen
Lerne CSS Transitions für smooth Effekte und Animations für komplexe Bewegungen: transition, animation, keyframes, timing-functions.
CSS Backgrounds & Borders - Hintergründe & Rahmen stylen
Lerne alles über CSS Backgrounds (Farben, Bilder, Gradients) und Borders (border-radius, box-shadow) für modernes Design.
CSS Basics - Deine Seite gestalten
Lerne, wie du mit CSS deine HTML-Seiten zum Leben erweckst. Farben, Schriftarten, Layouts - alles was du für schöne Webseiten brauchst.