CSS Protipps
Eine Sammlung von Tipps, die Ihnen helfen, Ihre CSS-Kenntnisse auf Profi-Niveau zu bringen. Jeder Eintrag ist ein in sich geschlossenes Muster – wenden Sie das an, das zum vorliegenden Problem passt.
Verwenden Sie einen CSS-Reset
CSS-Resets helfen, die Stilkonsistenz über verschiedene Browser hinweg zu erzwingen, indem sie eine saubere Ausgangsbasis für das Styling von Elementen schaffen. Es gibt viele Reset-Muster, oder Sie können einen vereinfachten Reset-Ansatz verwenden:
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
Jetzt werden Elemente von Abständen befreit und box-sizing ermöglicht die Verwaltung von Layouts mit dem CSS-Box-Modell.
Demo
[!TIP] Wenn Sie den unten stehenden Tipp Erben von
box-sizingbefolgen, können Sie diebox-sizing-Eigenschaft in Ihrem CSS-Reset weglassen.
Erben von box-sizing
Lassen Sie box-sizing von html erben:
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
Dies erleichtert die Änderung von box-sizing in Plugins oder anderen Komponenten, die ein anderes Verhalten nutzen.
Demo
Verwenden Sie all: unset mit Bedacht für Komponenten-Resets
Wenn Sie die Eigenschaften eines Elements zurücksetzen, können Sie jede Eigenschaft einzeln zurücksetzen:
button {
background: none;
border: none;
color: inherit;
font: inherit;
outline: none;
padding: 0;
}
Oder verwenden Sie die Kurzschreibweise all mit unset. all: unset setzt fast alle Eigenschaften zurück (außer
unicode-bidi, direction und benutzerdefinierten Eigenschaften) – geerbte Props werden auf inherit zurückgesetzt, andere auf den Anfangswert. Ein <button> wird zu display: inline und verliert seine native Box. Stellen Sie daher nach dem Zurücksetzen immer Layout und Fokus wieder her.
button.reset {
all: unset;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
button.reset:focus-visible {
outline: 2px solid currentColor;
outline-offset: 0.15em;
}
[!TIP] Um das User-Agent-Stylesheet anstelle einer leeren Ausgangsbasis wiederherzustellen, verwenden Sie
all: revert– siehe Reset-Absicht:unsetvsrevertim Modern-CSS-Abschnitt.
Verwenden Sie :not(), um Ränder bei Navigationen gezielt zu setzen/entfernen
Anstatt den Rand zu setzen...
/* Rand hinzufügen */
.nav li {
border-right: 1px solid #666;
}
...und ihn dann vom letzten Element zu entfernen...
/* Rand entfernen */
.nav li:last-child {
border-right: none;
}
...verwenden Sie die :not()-Pseudoklasse, um den Rand nur auf die gewünschten Elemente anzuwenden:
.nav li:not(:last-child) {
border-right: 1px solid #666;
}
Hier wird der CSS-Selektor so gelesen, wie ein Mensch ihn beschreiben würde.
Demo
Prüfen, ob eine Schriftart lokal installiert ist
Sie können prüfen, ob eine Schriftart lokal installiert ist, bevor Sie sie remote abrufen – das ist auch ein guter Performance-Tipp.
@font-face {
font-family: "Dank Mono";
src:
/* Vollständiger Name */ local("Dank Mono"), /* Postscript-Name */ local("Dank Mono"),
/* Andernfalls herunterladen! */ url("//...a.server/fonts/DankMono.woff");
}
code {
font-family: "Dank Mono", system-ui-monospace;
}
Dank an Adam Argyle für diesen Protipp und die Demo.
Fügen Sie line-height zu body hinzu
Sie müssen nicht jedem <p>, <h*>, et al. einzeln line-height hinzufügen. Fügen Sie es stattdessen zu body hinzu:
body {
line-height: 1.5;
}
So können Textelemente problemlos von body erben.
Demo
Setzen Sie :focus für Formularelemente
Sehende Tastaturbenutzer verlassen sich auf den Fokus, um zu bestimmen, wo Tastatureingaben auf der Seite landen. Gestalten Sie den Fokus für Formularelemente auffälliger und einheitlicher als die Standardimplementierung des Browsers:
a:focus,
button:focus,
input:focus,
select:focus,
textarea:focus {
box-shadow: none;
outline: #000 dotted 2px;
outline-offset: 0.05em;
}
Demo
[!TIP] In modernem Code bevorzugen Sie
:focus-visible, damit Tastaturbenutzer einen klaren Fokusring behalten, ohne bei jedem Mausklick Fokus-Stile anzuzeigen.
Vertikale Zentrierung von allem
Bevorzugen Sie Grid mit einer dynamischen Viewport-Einheit auf Mobilgeräten – 100vh entspricht dem großen Viewport und kann sich falsch verhalten, wenn Browser-Symbolleisten ein-/ausgeblendet werden. Verwenden Sie mit logischen Eigenschaften 100dvb (dynamischer Viewport-Block).
.center-page {
min-block-size: 100dvb;
display: grid;
place-items: center;
}
Flexbox funktioniert auf die gleiche Weise, sobald das Elternelement eine definierte Blockgröße hat:
html,
body {
min-block-size: 100%;
}
body {
align-items: center;
display: flex;
justify-content: center;
}
[!NOTE] Legacy-Muster:
height: 100vh+place-items: centertaucht immer noch in älteren Tutorials auf. Bevorzugen Siedvh/dvb/svh/lvhfür vollständige Viewport-Layouts auf Mobilgeräten – siehe MDN zu Viewport-relativen Längen.
[!TIP] Möchten Sie etwas anderes zentrieren? CSS-Tricks hat einen guten Artikel darüber, wie das geht.
Demo
Verwenden Sie aspect-ratio anstelle von Höhe/Breite
Die Eigenschaft aspect-ratio ermöglicht es Ihnen, Elemente einfach zu dimensionieren und ein konsistentes Breite-zu-Höhe-Verhältnis beizubehalten. Dies ist unglaublich nützlich im responsiven Webdesign, um Layoutverschiebungen zu vermeiden. Verwenden Sie object-fit zusammen damit, um zu verhindern, dass das Layout gestört wird, wenn sich die Höhen-/Breitenwerte von Bildern ändern.
img {
aspect-ratio: 16 / 9; /* Breite / Höhe */
object-fit: cover;
}
Erfahren Sie mehr über die aspect-ratio-Eigenschaft in diesem web.dev-Artikel.
Demo
Komma-getrennte Listen
Lassen Sie Listenelemente wie eine echte, komma-getrennte Liste aussehen:
ul > li:not(:last-child)::after {
content: ",";
}
Verwenden Sie die :not()-Pseudoklasse, und es wird kein Komma zum letzten Element hinzugefügt.
[!NOTE] Dieser Tipp ist möglicherweise nicht ideal für die Barrierefreiheit, insbesondere für Screenreader. Und Kopieren/Einfügen aus dem Browser funktioniert nicht mit CSS-generiertem Inhalt. Gehen Sie vorsichtig vor.
Elemente mit negativem nth-child auswählen
Verwenden Sie negatives nth-child in CSS, um die Elemente 1 bis n auszuwählen.
li {
display: none;
}
/* Elemente 1 bis 3 auswählen und anzeigen */
li:nth-child(-n + 3) {
display: block;
}
Oder, da Sie bereits etwas über die Verwendung von :not() gelernt haben, versuchen Sie:
/* Alle Elemente außer den ersten 3 auswählen und anzeigen */
li:not(:nth-child(-n + 3)) {
display: block;
}
Demo
Verwenden Sie SVG für Symbole
Es gibt keinen Grund, SVG für Symbole nicht zu verwenden:
.logo {
background: url("logo.svg");
}
SVG skaliert gut für alle Auflösungstypen und wird in allen Browsern bis zurück zum IE9 unterstützt. Werfen Sie Ihre .png-, .jpg- oder .gif-jif-whatev-Dateien weg.
[!NOTE] Wenn Sie nur aus SVG bestehende Symbolschaltflächen für sehende Benutzer haben und das SVG nicht geladen werden kann, hilft dies, die Barrierefreiheit zu erhalten:
.no-svg .icon-only::after {
content: attr(aria-label);
}
Verwenden Sie den „Lobotomized Owl“-Selektor
Es mag einen seltsamen Namen haben, aber die Verwendung des Universalselektors (*) mit dem benachbarten Geschwisterselektor (+) kann eine mächtige CSS-Fähigkeit bieten:
* + * {
margin-top: 1.5em;
}
In diesem Beispiel erhalten alle Elemente im Dokumentfluss, die anderen Elementen folgen, margin-top: 1.5em.
[!TIP] Mehr über den „Lobotomized Owl“-Selektor erfahren Sie in Heydon Pickings Artikel auf A List Apart.
Demo
Verwenden Sie max-height für reine CSS-Schieberegler
Implementieren Sie CSS-only-Schieberegler mit max-height und verstecktem Überlauf:
.slider {
max-height: 200px;
overflow-y: hidden;
width: 300px;
}
.slider:hover {
max-height: 600px;
overflow-y: scroll;
}
Das Element dehnt sich beim Hover auf den max-height-Wert aus, und der Schieberegler wird als Ergebnis des Überlaufs angezeigt.
Tabellenzellen mit gleicher Breite
Tabellen können mühsam zu handhaben sein. Versuchen Sie table-layout: fixed, um Zellen auf gleicher Breite zu halten:
.calendar {
table-layout: fixed;
}
Schmerzfreie Tabellenlayouts.
Demo
Werden Sie Margin-Hacks mit Flexbox los
Bei der Arbeit mit Spaltenabständen können Sie nth-, first- und last-child-Hacks vermeiden, indem Sie die Flexbox-Eigenschaft space-between verwenden:
.list {
display: flex;
justify-content: space-between;
}
.list .person {
flex-basis: 23%;
}
Jetzt erscheinen Spaltenabstände immer gleichmäßig verteilt.
Verwenden Sie Attributselektoren mit leeren Links
Zeigen Sie Links an, wenn das <a>-Element keinen Textwert hat, das href-Attribut aber einen Link enthält:
a[href^="http"]:empty::before {
content: attr(href);
}
Das ist wirklich praktisch.
Demo
[!NOTE] Dieser Tipp ist möglicherweise nicht ideal für die Barrierefreiheit, insbesondere für Screenreader. Und Kopieren/Einfügen aus dem Browser funktioniert nicht mit CSS-generiertem Inhalt. Gehen Sie vorsichtig vor.
Spezifität besser mit :is() kontrollieren
Die :is()-Pseudoklasse wird verwendet, um mehrere Selektoren gleichzeitig anzusprechen, Redundanz zu reduzieren und die Lesbarkeit des Codes zu verbessern. Dies ist unglaublich nützlich, um große Selektoren in einer kompakteren Form zu schreiben.
:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
color: green;
}
Die obige Regel entspricht den folgenden zahlreichen Selektoren...
section h1,
section h2,
section h3,
section h4,
section h5,
section h6,
article h1,
article h2,
article h3,
article h4,
article h5,
article h6,
aside h1,
aside h2,
aside h3,
aside h4,
aside h5,
aside h6,
nav h1,
nav h2,
nav h3,
nav h4,
nav h5,
nav h6 {
color: green;
}
Demo
Stylen Sie „Standard“-Links
Fügen Sie einen Stil für „Standard“-Links hinzu:
a[href]:not([class]) {
color: #008000;
text-decoration: underline;
}
Jetzt erhalten Links, die über ein CMS eingefügt werden und normalerweise kein class-Attribut haben, eine Unterscheidung, ohne die Kaskade generisch zu beeinflussen.
Intrinsische Verhältnis-Boxen (Legacy-Fallback)
[!NOTE] Nur Legacy. Bevorzugen Sie
aspect-ratio(Baseline Weit verbreitet) für neuen Code. Behalten Sie diesen Padding-Hack nur bei, wenn Sie sehr alte Browser unterstützen müssen oder ein Muster benötigen, das älter alsaspect-ratioist.
Um eine Box mit einem intrinsischen Verhältnis zu erstellen, wenden Sie einen oberen oder unteren Padding auf ein Div an:
.container {
height: 0;
padding-bottom: 20%;
position: relative;
}
.container div {
border: 2px dashed #ddd;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
Die Verwendung von 20% für den Padding macht die Höhe der Box gleich 20% ihrer Breite. Unabhängig von der Viewport-Breite behält das untergeordnete Div sein Seitenverhältnis (100% / 20% = 5:1).
Demo
Stylen Sie defekte Bilder
Machen Sie defekte Bilder mit ein wenig CSS ästhetisch ansprechender:
img {
display: block;
font-family: sans-serif;
font-weight: 300;
height: auto;
line-height: 2;
position: relative;
text-align: center;
width: 100%;
}
Fügen Sie nun Regeln für Pseudoelemente hinzu, um eine Benutzernachricht und die URL-Referenz des defekten Bildes anzuzeigen:
img::before {
content: "Es tut uns leid, das Bild unten ist defekt :(";
display: block;
margin-bottom: 10px;
}
img::after {
content: "(url: " attr(src) ")";
display: block;
font-size: 12px;
}
[!TIP] Erfahren Sie mehr über das Styling für dieses Muster in Ire Aderinokuns Artikel.
Verwenden Sie rem für globale Größenangaben; verwenden Sie em für lokale Größenangaben
Nachdem Sie die Basis-Schriftgröße im Root festgelegt haben (html { font-size: 100%; }), setzen Sie die Schriftgröße für Textelemente auf em:
h2 {
font-size: 2em;
}
p {
font-size: 1em;
}
Setzen Sie dann die Schriftgröße für Module auf rem:
article {
font-size: 1.25rem;
}
aside .module {
font-size: 0.9rem;
}
Jetzt wird jedes Modul abgekapselt und ist einfacher zu stylen, wartbarer und flexibler.
Autoplay-Videos ohne Ton ausblenden
Dies ist ein großartiger Trick für ein benutzerdefiniertes Benutzer-Stylesheet. Vermeiden Sie es, einen Benutzer mit Ton von einem Video zu überlasten, das automatisch abgespielt wird, wenn die Seite geladen wird. Wenn der Ton nicht stummgeschaltet ist, zeigen Sie das Video nicht an:
video[autoplay]:not([muted]) {
display: none;
}
Wieder einmal nutzen wir die :not()-Pseudoklasse.
Verwenden Sie :root für flexible Schriftgrößen
Die Schriftgröße in einem responsiven Layout sollte sich an jeden Viewport anpassen können. Sie können die Schriftgröße basierend auf der Viewport-Höhe und -Breite mit :root berechnen:
:root {
font-size: calc(1vw + 1vh + 0.5vmin);
}
Jetzt können Sie die root em-Einheit basierend auf dem von :root berechneten Wert verwenden:
body {
font: 1rem/1.6 sans-serif;
}
Demo
Setzen Sie font-size für Formularelemente für ein besseres mobiles Erlebnis
Um zu vermeiden, dass mobile Browser die Schriftgröße von Formularelementen beim Tippen vergrößern, setzen Sie die Schriftgröße explizit:
input[type="text"],
input[type="number"],
select,
textarea {
font-size: 16px;
}
Dadurch wird verhindert, dass iOS Safari und andere Browser die Schriftgröße unerwartet ändern, wenn das Element fokussiert wird.
Modernes CSS (nach Baseline)
Weit verbreitet (Baseline)
aspect-ratio
Inzwischen weit verbreitete Unterstützung. Siehe [Verwenden Sie aspect-ratio anstelle von Höhe/Breite](#verwenden Sie-aspect-ratio-anstelle-von-höhebreite) oben.
:is() und :where()
Siehe Kontrollieren Sie die Spezifität besser mit :is() oben.
(:where() hat die gleiche Syntax, aber seine Spezifität ist immer Null – nützlich für Resets.
/* Spezifität = 0,0,1 */
:where(article, section) p {
color: red;
}
/* Spezifität = 0,0,1 (überschreibt oben) */
p {
color: blue;
}
[!NOTE] Wenn
:where()in einer vollständigen Regel keine Fehlerbehandlung hat – wenn einer der Selektoren ungültig ist, wird die gesamte Liste als ungültig betrachtet.
Logische Eigenschaften (inset-inline, margin-block, etc.)
Logische Eigenschaften respektieren den Schreibmodus und die Textrichtung des Dokuments, sodass Sie Layouts schreiben können, die automatisch von links-nach-rechts zu rechts-nach-links (und von oben-nach-unten zu unten-nach-oben) wechseln.
.element {
/* Anstatt: margin-left: 1rem; margin-right: 1rem;
Verwenden Sie: */
margin-inline: 1rem;
/* Anstatt: padding-top: 0; padding-bottom: 0;
Verwenden Sie: */
padding-block: 0;
/* Anstatt: left: 0; right: 0;
Verwenden Sie: */
inset-inline: 0;
}
Erfahren Sie mehr in der MDN-Dokumentation.
min(), max(), clamp()
Mathematische CSS-Funktionen wählen einen Wert basierend auf dem kleinsten/größten Element oder einem begrenzten Bereich aus. Perfekt für fließende Typografie.
/* Fließende Schriftgröße: niemals kleiner als 1rem, niemals größer als 3rem */
h1 {
font-size: clamp(1rem, 1rem + 2vw, 3rem);
}
/* Reaktionsfreudiger Container: maximal 1200px, aber passt sich dem Viewport an */
.container {
width: min(1200px, 100% - 2rem);
}
gap für Flexbox
.flex-layout {
display: flex;
flex-wrap: wrap;
gap: 1rem; /* Funktioniert sowohl horizontal als auch vertikal */
}
gap funktioniert sowohl in Grid als auch in Flexbox und vermeidet Margin-Hacks.
accent-color
Setzt die Farbe von Formularsteuerelementen (Checkboxen, Radios, Bereich, Fortschritt):
:root {
accent-color: #0066cc;
}
input[type="checkbox"] {
accent-color: custom; /* Erbt von :root */
}
[!NOTE]
accent-colorrespektiert dieprefers-contrast: more-Einstellung nicht automatisch. Testen Sie Kontrast und Fokus separat.
Neu verfügbar (Baseline 2023–2025)
@scope (Baseline 2025)
Begrenzen Sie Selektoren innerhalb einer Komponente, sodass Stile nicht nach außen „lecken“:
@scope (.card) {
:scope {
/* Betrifft nur .card selbst */
border: 1px solid #ccc;
}
p {
/* Betrifft nur <p> innerhalb von .card */
margin-block: 0.5em;
}
}
[!TIP]
@scopekann die Abhängigkeit von BEM oder anderen Namenskonventionen reduzieren, aber testen Sie weiterhin die spezifischen Anwendungsfälle Ihrer Komponente.
text-wrap: balance / pretty
h1, h2, h3 {
text-wrap: balance; /* Versucht, Zeilenlängen auszugleichen */
}
blockquote {
text-wrap: pretty; /* Vermeidet einsame Wörter / Waisen */
}
[!NOTE]
balancekann bei breiten Containern zu Leistungskosten führen – auf lange Textblöcke beschränken.
content-visibility: auto
Überspringt das Rendering von Elementen außerhalb des Bildschirms und verbessert so die anfängliche Seitenladezeit erheblich.
.lazy-section {
content-visibility: auto;
contain-intrinsic-size: 500px; /* Platzhaltergröße, bevor der Inhalt gerendert wird */
}
[!WARNING]
content-visibility: autokann die Lesereihenfolge für Screenreader beeinträchtigen, wenn es für fokussierbare oder interaktive Elemente verwendet wird. Reservieren Sie es für reine Layout-Container.
has()-Selektor
Der „Eltern“-Selektor – wählen Sie ein Element basierend darauf aus, was es enthält:
/* Ein <figure> mit einem <figcaption> hervorheben */
figure:has(figcaption) {
border: 1px solid #ccc;
padding: 1rem;
}
/* Stile auf eine Karte anwenden, wenn ihr Link derzeit fokussiert ist (benutzerdefiniertes Stylesheet) */
.card:has(a:focus-visible) {
outline: 2px solid Highlight;
}
/* Kein Rand mehr auf der letzten Karte */
.card-list:not(:has(.card:last-child)) .card {
border-bottom: 1px solid #ddd;
}
[!TIP]
:has()ist leistungsstark, aber denken Sie an die Leistung – vermeiden Sie tief verschachteltes:has()(:has(:has(...))).
@container-Abfragen
/* Kontainer definieren */
.card-container {
container-type: inline-size;
container-name: card;
}
/* Wenn der Kontainer >= 400px breit ist */
@container card (min-width: 400px) {
.card-layout {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
/* Stilabfrage: Wenn der Kontainer eine bestimmte benutzerdefinierte Eigenschaft hat */
@container card style(--theme: dark) {
.card {
background: #222;
color: #eee;
}
}
[!TIP] Kombinieren Sie Container-Abfragen mit
:has(), um Komponenten unabhängig von der Viewport-Größe reagieren zu lassen.
Eingeschränkte Unterstützung (Frühphase)
scroll-driven-animations
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
.animated-element {
animation: fade-in linear;
animation-timeline: view(); /* Fortschritt basierend auf der Scrollposition */
animation-range: entry 0% entry 100%;
}
[!WARNING] Die Unterstützung ist auf Chromium-Browser beschränkt (2025). Verwenden Sie sie als progressive Verbesserung mit einem Fallback ohne Animation.
@starting-style und transition-behavior
Ermöglicht Übergänge von/zu display: none:
.new-element {
display: none;
opacity: 0;
transition: opacity 0.3s, display 0.3s allow-discrete;
}
.new-element.show {
display: block;
opacity: 1;
}
@starting-style {
.new-element.show {
opacity: 0;
}
}
CSS-Verschachtelung (native Syntax)
.card {
border: 1px solid #ddd;
& .header {
font-weight: bold;
}
& .body {
padding: 1rem;
}
@media (width >= 768px) {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
[!NOTE] Native Verschachtelung hat einige Einschränkungen (z. B. erfordert
&eine bestimmte Syntax, wenn es auf Element-Tags angewendet wird). Preprozessor-Verschachtelung (Sass/PostCSS) bleibt für komplexe Muster praktikabel.
Globale Unterstützungs- und Barrierefreiheitshinweise
- Baseline ist kein Barrierefreiheitssignal. Testen Sie Kontrast, Tastaturfokus und Screenreader-Kompatibilität immer separat.
- Verwenden Sie
@supports, um fortschrittliche Funktionen als progressive Verbesserungen zu verwenden – Kerninhalte und Interaktionen sollten ohne die neueste CSS-Funktion zugänglich sein. - Respektieren Sie die Benutzereinstellungen:
prefers-reduced-motion: Deaktivieren oder reduzieren Sie nicht wesentliche Animationen.prefers-contrast: more: Sicherstellen ausreichender Kontrast.prefers-color-scheme: Helle/dunkle Modi unterstützen.
Reset-Absicht: unset vs revert
| Absicht | Verwendung | Effekt |
|---|---|---|
| Leere Ausgangsbasis | all: unset | Erbt geerbte Props, setzt andere auf Anfangswerte zurück |
| Wiederherstellung des Browser-Standards | all: revert | Setzt geerbte Props auf den geerbten Wert und andere auf den UA-Standard zurück |
Minimales Button-Reset (mit revert):
button.reset {
all: revert;
cursor: pointer;
}
Dies stellt das native Button-Styling wieder her (Hover, Fokus, Klick) und überschreibt gleichzeitig, was ein Reset-Stylesheet möglicherweise entfernt hat.
Bevorzugen Sie :focus-visible gegenüber :focus
focus-visible zeigt nur dann einen Fokusring an, wenn der Browser dies für die Tastaturnavigation
für erforderlich hält (z. B. Tab-Taste) und nicht bei Mausklicks:
/* Keyboard-Fokus immer sichtbar machen */
:focus-visible {
outline: 2px solid Highlight;
outline-offset: 2px;
}
/* Überschreiben von `outline: none` auf Maus-Fokus
(wird von den meisten Reset-Stylesheets vermieden) – stattdessen: */
*:focus:not(:focus-visible) {
outline: none;
}
Quellen
- AllThingsSmitty/css-protips – ursprüngliche Sammlung
- MDN Baseline – Browser-Kompatibilitätssignal
- web.dev – Lernen Sie CSS zu lieben – moderner CSS-Leitfaden
- MDN CSS-Selektor-Referenz