::before, ::after und alle modernen Tricks
CSS Pseudo-Elemente sind eine der mächtigsten, aber am häufigsten oberflächlich genutzten Funktionen von CSS. ::before und ::after mit content und counter, die modernen Pseudo-Elemente ::marker, ::selection und ::first-line – dieser Artikel zeigt, was wirklich möglich ist und welche Tricks in modernem CSS funktionieren.
Inhaltsverzeichnis
- 1. Pseudo-Elemente verstehen
- 2. ::before und ::after: Grundlagen und Grenzen
- 3. Die content-Eigenschaft vollständig genutzt
- 4. CSS Counter mit ::before und counter()
- 5. ::marker — Listenzeichen stylisch gestalten
- 6. ::selection — Textauswahl anpassen
- 7. ::first-line und ::first-letter
- 8. Fortgeschrittene ::before/::after-Tricks
- 9. Pseudo-Elemente im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Pseudo-Elemente verstehen
CSS Pseudo-Elemente sind syntaktische Konstrukte, die bestimmte Teile eines Elements oder zusätzliche virtuelle Elemente beschreiben, die nicht im HTML-Markup existieren. Der doppelte Doppelpunkt :: unterscheidet sie seit CSS3 von Pseudoklassen wie :hover oder :focus – obwohl Browser aus Kompatibilitätsgründen auch den einfachen Doppelpunkt für die klassischen Pseudo-Elemente noch akzeptieren. Die bekanntesten Pseudo-Elemente sind ::before und ::after, aber das Spektrum reicht weit darüber hinaus.
Die Unterscheidung zwischen Pseudoklassen und Pseudo-Elementen ist konzeptionell wichtig: Pseudoklassen selektieren ein Element in einem bestimmten Zustand. Pseudo-Elemente hingegen selektieren und erstellen einen bestimmten Teil eines Elements oder fügen ein neues virtuelles Element ein. ::before erstellt ein Kindelement vor dem ersten Kind des selektierten Elements. ::after nach dem letzten Kind. ::first-line selektiert die erste gerenderte Textzeile. ::marker selektiert das Listenzeichen. ::selection selektiert markierten Text.
Ein häufiges Missverständnis betrifft die Zugänglichkeit von Pseudo-Elementen. Inhalte in content von ::before und ::after sind für Screenreader in den meisten Implementierungen sichtbar, jedoch nicht einheitlich – manche Browser lesen content-Text vor, andere nicht. Für alle semantisch relevanten Inhalte gilt daher: niemals ausschließlich in Pseudo-Elementen platzieren. Dekorative Elemente, Icons über content: "" und visuelle Hilfsmittel dagegen sind genau der richtige Anwendungsfall.
2. ::before und ::after: Grundlagen und Grenzen
Das grundlegende Nutzungsmuster von ::before und ::after erfordert immer eine content-Eigenschaft – ohne sie werden die Pseudo-Elemente nicht gerendert. content: "" ist der gebräuchlichste Wert, um ein leeres Pseudo-Element zu erzeugen, das rein visuell funktioniert. Mit position: absolute auf dem Pseudo-Element und position: relative auf dem Elternelement können dekorative Overlays, Badges, Unterstreichungseffekte und Icon-Platzierungen ohne zusätzliche HTML-Elemente implementiert werden.
Die Grenzen von ::before und ::after sind wichtig zu kennen: Sie funktionieren nur auf Container-Elementen, nicht auf Replaced Elements wie <img>, <input>, <br> oder <hr>. Der Grund: Replaced Elements haben keinen eigenen Content, dem man etwas voranstellen oder anhängen könnte. Ein häufiger Fehler ist der Versuch, ::before auf einem <img> zu nutzen. Für Icon-Implementierungen auf Input-Feldern benötigt man daher immer ein Wrapper-Element oder verwendet CSS-Backgrounds direkt auf dem Input.
/* Classic ::before / ::after patterns */
/* Decorative underline effect without extra HTML */
.link-underline {
position: relative;
text-decoration: none;
color: #7c3aed;
}
.link-underline::after {
content: "";
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: linear-gradient(90deg, #7c3aed, #c4b5fd);
border-radius: 1px;
transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.link-underline:hover::after,
.link-underline:focus-visible::after {
width: 100%;
}
/* Badge counter on icon */
.icon-with-badge {
position: relative;
display: inline-flex;
}
.icon-with-badge::after {
content: attr(data-count);
position: absolute;
top: -6px;
right: -8px;
min-width: 18px;
height: 18px;
padding: 0 4px;
background: #7c3aed;
color: #fff;
font-size: 10px;
font-weight: 700;
border-radius: 9px;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
/* Overlay pattern for hover effect */
.card-overlay {
position: relative;
overflow: hidden;
}
.card-overlay::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(74,29,150,0.0), rgba(124,58,237,0.3));
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
z-index: 1;
}
.card-overlay:hover::before {
opacity: 1;
}
3. Die content-Eigenschaft vollständig genutzt
Die content-Eigenschaft von Pseudo-Elementen kann weit mehr als einen einfachen String. content: attr(data-label) liest ein HTML-Data-Attribut aus und gibt es im Pseudo-Element aus – ein mächtiges Muster für Tooltips, Badges und dynamische Labels ohne JavaScript. content: counter(my-counter) gibt den aktuellen Zählerwert aus. content: open-quote und content: close-quote fügen sprachspezifische Anführungszeichen ein, die per quotes konfigurierbar sind.
Mehrere Werte können in content mit Leerzeichen kombiniert werden: content: "§ " counter(section) " — " attr(data-title) erzeugt einen kombinierten Wert aus String, Zähler und Data-Attribut. Seit CSS Images Level 4 unterstützt content auch url() für kleine Inline-Bilder. Die alt-Funktion in content erlaubt es, einen alternativen Text für Screenreader anzugeben: content: url(icon.svg) / "Icon-Beschreibung". Damit werden Icons in Pseudo-Elementen zugänglich, wenn sie semantisch relevant sind.
4. CSS Counter mit ::before und counter()
CSS-Counter sind eines der am häufigsten übersehenen Features des Browsers. Sie ermöglichen automatisches Durchnummerieren von Elementen vollständig in CSS, ohne JavaScript und ohne manuell HTML-Attribute zu setzen. Das Grundprinzip: counter-reset: section initialisiert einen Counter auf einem Elternelement. counter-increment: section auf Kindelementen erhöht den Counter mit jeder Anwendung. counter(section) in der content-Eigenschaft eines Pseudo-Elements gibt den aktuellen Wert aus.
Verschachtelte Counter – typisch für mehrstufige Gliederungen – nutzen counters(section, "."): Diese Funktion gibt alle Counter der Hierarchie mit dem angegebenen Separator aus und erzeugt automatisch Nummerierungen wie "1.2.3". Das ist besonders für technische Dokumentation, Rechtsdokumente und Gliederungsansichten wertvoll. In Kombination mit ::before lassen sich so vollständig automatisch nummerierte Listen, Abschnittsnummern und Inhaltsverzeichnisse bauen, die sich automatisch anpassen, wenn Elemente hinzukommen oder entfernt werden.
/* CSS Counter for automatic section numbering */
article {
counter-reset: section;
}
article h2 {
counter-increment: section;
}
article h2::before {
content: counter(section) ". ";
color: #7c3aed;
font-variant-numeric: tabular-nums;
}
/* Nested counters for outlines */
.outline {
counter-reset: chapter;
}
.outline .chapter {
counter-reset: subchapter;
counter-increment: chapter;
}
.outline .subchapter {
counter-increment: subchapter;
}
.outline .chapter > h3::before {
content: counter(chapter) " ";
font-weight: 700;
color: #4a1d96;
}
.outline .subchapter > h4::before {
/* counters() uses all levels with separator "." */
content: counters(chapter, ".") "." counter(subchapter) " ";
color: #7c3aed;
}
/* Custom list style using counter */
.custom-list {
counter-reset: list-item-custom;
list-style: none;
padding: 0;
}
.custom-list li {
counter-increment: list-item-custom;
padding-left: 2.5rem;
position: relative;
margin-bottom: 0.75rem;
}
.custom-list li::before {
content: counter(list-item-custom, decimal-leading-zero);
position: absolute;
left: 0;
top: 0;
font-size: 0.75rem;
font-weight: 700;
color: #7c3aed;
background: #ede9fe;
border-radius: 4px;
padding: 1px 5px;
line-height: 1.6;
}
5. ::marker — Listenzeichen stylisch gestalten
Das Pseudo-Element ::marker selektiert das automatisch erzeugte Listenzeichen von <li>-Elementen und summary-Elementen. Vor der Einführung von ::marker war es extrem schwierig, Listenzeichen zu stylen – der übliche Workaround war list-style: none und dann ::before für ein manuelles Zeichen. Mit ::marker kann man direkt das native Listenzeichen ansprechen, ohne den Standard-Rendering-Mechanismus zu umgehen.
Die Properties, die auf ::marker anwendbar sind, sind bewusst eingeschränkt: color, font, font-variant-numeric, content, unicode-bidi, direction, white-space und animierbare Properties. Das ist deutlich weniger als bei ::before und ::after, aber für die meisten Anwendungsfälle ausreichend. Besonders praktisch: content: "" auf ::marker entfernt das Listenzeichen komplett, ohne list-style: none zu benötigen, was die native Listenstruktur für Screenreader erhält.
6. ::selection — Textauswahl anpassen
Das Pseudo-Element ::selection erlaubt das Styling von vom Nutzer ausgewähltem Text. Das ist eine subtile, aber wirkungsvolle Designdetail-Möglichkeit – die Markierungsfarbe kann an die Brand-Farben angepasst werden und schafft eine konsistente visuelle Identität bis in die kleinsten Details. Die unterstützten Properties sind eingeschränkt: color, background-color, text-decoration, text-shadow und caret-color. Background-Images und andere CSS-Properties funktionieren nicht.
Ein wichtiger Zugänglichkeitsaspekt bei ::selection: Das Kontrastverhältnis zwischen dem Selektionstext und dem Selektionshintergrund muss WCAG-konform sein. Viele Designs setzen eine Markenfarbe als Hintergrund, vergessen aber, die Textfarbe explizit zu setzen – was zu schlechtem Kontrast führen kann, wenn die Standard-Textfarbe mit dem Markierungshintergrund schlecht harmoniert. Beide Werte immer explizit setzen und mit einem Kontrast-Checker prüfen.
/* ::marker customization — preserves semantic list structure */
ul.styled-list {
list-style-type: disc;
}
ul.styled-list li::marker {
color: #7c3aed;
font-size: 1.2em;
}
/* Custom content in marker */
ol.checkmarks li::marker {
content: "✓ ";
color: #059669;
font-weight: 700;
}
/* Remove marker while keeping accessible list semantics */
nav ul li::marker {
content: "";
}
/* ::selection — brand-consistent text highlighting */
::selection {
background-color: #c4b5fd;
color: #1e1b4b;
}
/* Inverted selection for dark backgrounds */
.dark-section ::selection {
background-color: #4a1d96;
color: #ede9fe;
}
/* ::first-line — style the first rendered line only */
.article-body p:first-of-type::first-line {
font-variant: small-caps;
letter-spacing: 0.04em;
font-weight: 600;
color: #4a1d96;
}
/* ::first-letter — drop cap effect */
.article-body p:first-of-type::first-letter {
float: left;
font-size: 3.5em;
line-height: 0.85;
margin-right: 0.08em;
color: #7c3aed;
font-weight: 900;
}
7. ::first-line und ::first-letter
Die Pseudo-Elemente ::first-line und ::first-letter sind klassische Typografie-Features, die aus der Drucktradition stammen. ::first-line selektiert die erste gerenderte Zeile eines Block-Elements – das ist eine dynamische Selektion, da sich die erste Zeile beim Ändern der Fenstergröße ändert. Properties wie font-variant, letter-spacing, text-decoration und color können darauf angewendet werden, nicht aber Layout-Properties wie margin oder padding.
::first-letter ermöglicht das klassische Druckdesign-Feature der Initiale oder des Drop Cap: Der erste Buchstabe eines Absatzes wird größer dargestellt und floated links, sodass sich der restliche Text darum herum anordnet. ::first-letter unterstützt vollständiges Box-Modell-Styling inklusive float, padding, margin, border und font-size. Es gilt dabei eine wichtige Einschränkung: Das Element muss ein Block-Level-Container sein, und ::first-letter erfasst nur den allerersten typografischen Buchstaben – kein voranstehendes Anführungszeichen wird ignoriert, sondern miterfasst.
8. Fortgeschrittene ::before/::after-Tricks
Einige der mächtigsten Anwendungen von CSS Pseudo-Elementen sind weniger bekannt. Das attr()-Pattern in content ist für Tooltips nutzbar: Ein Element mit data-tooltip="Beschreibung" zeigt den Tooltip über ::after { content: attr(data-tooltip); } an – ohne JavaScript, nur mit CSS für Positionierung und Sichtbarkeit via :hover. Mit Anchor Positioning und der Popover API kann dieses Muster heute sogar zuverlässig positioniert werden.
Das Clearfix-Pattern – eines der historisch wichtigsten Pseudo-Element-Muster – ist heute dank Flexbox und Grid veraltet, aber instruktiv: .clearfix::after { content: ""; display: table; clear: both; } löste Floats auf, ohne HTML zu verändern. Modern geblieben sind dagegen Focus-Ring-Ersatz-Muster mit ::before, die bessere Kontrolle über den visuellen Fokusring bieten als das native Outline. Indem man outline: none auf dem Element und einen gestalteten Ring über ::before mit position: absolute und box-shadow implementiert, entstehen Fokus-Indikatoren, die sich exakt an das Element anpassen.
9. Pseudo-Elemente im Vergleich
Die verschiedenen CSS Pseudo-Elemente haben unterschiedliche Anwendungsbereiche, erlaubte Properties und Browser-Unterstützung. Die folgende Übersicht hilft, das richtige Pseudo-Element für den jeweiligen Anwendungsfall zu wählen.
| Pseudo-Element | Selektiert / Erstellt | Wichtigste Properties | Anwendungsfall |
|---|---|---|---|
| ::before | Erstes virtuelles Kindelement | content, position, alle CSS | Dekor, Icons, Overlays |
| ::after | Letztes virtuelles Kindelement | content, position, alle CSS | Badges, Underlines, Tooltips |
| ::marker | Listenzeichen von <li> | color, font, content | Styled Listen, benutzerdefinierte Zeichen |
| ::selection | Vom Nutzer ausgewählter Text | color, background-color | Brand-konsistente Textmarkierung |
| ::first-line | Erste gerenderte Textzeile | font-variant, color, letter-spacing | Typografie, Lead-Sätze |
Die Kombination mehrerer Pseudo-Elemente auf demselben Element ist möglich. Ein Button kann gleichzeitig ein ::before für einen dekorativen Hintergrundeffekt und ein ::after für ein animiertes Unterstreichen nutzen. Da jedes Element nur ein ::before und ein ::after hat, ist das die maximale Anzahl gleichzeitig nutzbarer generierter Elemente pro HTML-Element – ein häufiger Refaktorierungsschritt ist das Zusammenführen mehrerer visueller Effekte in einem dieser beiden Pseudo-Elemente.
Mironsoft
Modernes CSS, saubere Architekturen und wartbare Frontends
CSS-Architektur und saubere Komponent-Patterns?
Wir bauen wartbare CSS-Systeme mit modernen Pseudo-Element-Mustern, sauberem Tailwind-Code und minimalen JavaScript-Abhängigkeiten für eure Hyvä- und Magento-Projekte.
CSS-Review
Bestehende CSS-Codebase auf moderne Pseudo-Element-Muster analysieren
Komponenten
Buttons, Links, Listen und Typografie mit ::before/::after sauber implementieren
Tailwind v4.0
Pseudo-Element-Muster in Tailwind und Hyvä-Themes integrieren
10. Zusammenfassung
CSS Pseudo-Elemente sind ein unverzichtbares Werkzeug für sauberes, wartbares CSS ohne überflüssige HTML-Elemente. ::before und ::after mit der vollständigen content-API – inklusive attr(), counter() und kombinierten Werten – ermöglichen Dekorationen, automatische Nummerierungen und dynamische Labels. ::marker gibt endlich direkten Zugriff auf Listenzeichen, ohne die semantische Listenstruktur zu kompromittieren. ::selection erlaubt Brand-konsistente Textmarkierungen. ::first-line und ::first-letter bringen Drucktypografie ins Web.
Die fortgeschrittenen Muster – Tooltip-Implementierungen mit attr(), Focus-Ring-Ersatz, animierte Unterstreichungen und Overlay-Effekte – zeigen, dass CSS Pseudo-Elemente weit über einfache Dekorationen hinausgehen. In Kombination mit CSS Custom Properties, @property und modernen Layout-Features werden sie zu einem zentralen Bestandteil moderner CSS-Architekturen, die JavaScript-Abhängigkeiten minimieren und den Browser die Arbeit machen lassen.
CSS Pseudo-Elemente — Das Wichtigste auf einen Blick
::before / ::after
content: "" für leere Elemente. content: attr(data-x) für HTML-Attribute. Funktionieren nicht auf Replaced Elements (img, input).
CSS Counter
counter-reset + counter-increment + counter() in content. Verschachtelt mit counters(name, ".") für mehrstufige Nummerierung.
::marker
Direktes Styling von Listenzeichen. color, font, content erlaubt. content: "" entfernt das Zeichen ohne list-style: none.
::selection
Brand-Textmarkierung mit color + background-color. Immer beide Werte setzen — Kontrast prüfen für WCAG-Konformität.
11. FAQ: CSS Pseudo-Elemente
1Pseudo-Element vs. Pseudoklasse?
2::before auf img?
3Was kann content?
4CSS Counter?
5::marker?
6::selection?
7::first-line?
8Drop Cap mit CSS?
p::first-letter { float: left; font-size: 3.5em; line-height: 0.85; margin-right: 0.1em; } — Erstes Zeichen vergrößert, Text fließt darum.