Performance ist wichtig. Aber wenn dein CSS nach 6 Monaten ein Wartungs-Albtraum ist, nützt dir die beste Performance nichts.
Dieser Teil zeigt, wie du CSS schreibst, das skaliert.
1. Selector-Strategien & Spezifität
Das Spezifitäts-Problem
/* Tag: 1 Punkt */
div { color: black; }
/* Klasse: 10 Punkte */
.button { color: blue; }
/* ID: 100 Punkte */
#header { color: red; }
/* Inline: 1000 Punkte */
<div style="color: green;">
/* !important: ∞ Punkte */
.text { color: purple !important; }
Problem: Einmal !important, immer !important.
/* ❌ Spezifitäts-Hölle */
.button { background: blue; }
.button.primary { background: green !important; }
.button.primary.large { background: red !important; }
BEM: Block Element Modifier
/* ✅ Flache Spezifität */
.button { }
.button__icon { }
.button__text { }
.button--primary { }
.button--large { }
Vorteile:
- Immer gleiche Spezifität (10 Punkte)
- Keine Verschachtelung
- Selbstdokumentierend
Nachteile:
- Lange Klassennamen
- HTML wird “hässlich”
Utility-First (Tailwind-Stil)
<!-- ✅ Komponierbar, keine Spezifität -->
<button class="px-4 py-2 bg-blue-500 text-white rounded">
Click me
</button>
Vorteile:
- Keine CSS-Datei schreiben
- Keine Dead CSS
- Konsistent
Nachteile:
- HTML wird lang
- Repetitiv
Hybrid-Ansatz (Best Practice)
/* Base Komponente */
.button {
@apply px-4 py-2 rounded font-medium;
}
/* Varianten mit Data-Attributes */
.button[data-variant="primary"] {
@apply bg-blue-500 text-white;
}
.button[data-size="large"] {
@apply px-6 py-3 text-lg;
}
<button class="button" data-variant="primary" data-size="large">
Click me
</button>
Vorteil: Lesbar + wartbar + kein Spezifitäts-Krieg.
!important vermeiden
Legitime Nutzung:
/* ✅ OK - Utility-Klassen */
.hidden { display: none !important; }
.sr-only { position: absolute !important; }
Illegitime Nutzung:
/* ❌ Schlecht - Quick Fix */
.header {
margin-top: 20px !important; /* Warum nicht 20px? */
}
Lösung: Spezifität erhöhen oder Selektor umstrukturieren.
2. CSS-Architektur: Layers, Tokens, Utilities
@layer für Ordnung
/* ✅ Definiere Layer-Reihenfolge */
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; box-sizing: border-box; }
}
@layer base {
body { font-family: sans-serif; }
h1 { font-size: 2rem; }
}
@layer components {
.button { padding: 0.5rem 1rem; }
.card { border: 1px solid #ccc; }
}
@layer utilities {
.text-center { text-align: center !important; }
}
Vorteil: Utilities überschreiben immer Components, egal wo sie im Code stehen.
Design Tokens
:root {
/* Colors */
--color-primary: #3b82f6;
--color-primary-dark: #2563eb;
--color-primary-light: #60a5fa;
--color-gray-50: #f9fafb;
--color-gray-900: #111827;
/* Spacing */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
/* Typography */
--font-sans: 'Inter', sans-serif;
--font-mono: 'Fira Code', monospace;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
/* Radius */
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
}
/* Komponenten nutzen Tokens */
.button {
padding: var(--space-2) var(--space-4);
background: var(--color-primary);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
}
Vorteil: Ein Token ändern = alle Komponenten ändern sich.
Utilities vs. Komponenten
Faustregel:
- Komponente: Wird mehrfach verwendet, hat eigene Logik
- Utility: Atomare Helper-Klasse
/* ✅ Komponente */
.card {
padding: var(--space-4);
background: white;
border-radius: var(--radius-lg);
box-shadow: var(--shadow-md);
}
/* ✅ Utilities */
.mt-4 { margin-top: var(--space-4); }
.flex { display: flex; }
.items-center { align-items: center; }
3. Dead CSS & Bloat vermeiden
Das Problem
/* styles.css - 500 KB */
.button-legacy { } /* Wird nirgendwo genutzt */
.old-header { } /* Wurde ersetzt */
.test-class { } /* Vergessen zu löschen */
Nach 2 Jahren: 70% Dead CSS.
Detection Tools
PurgeCSS:
// purgecss.config.js
module.exports = {
content: ['./src/**/*.html', './src/**/*.js'],
css: ['./src/**/*.css'],
defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
}
UnCSS:
npm install -g uncss
uncss index.html > cleaned.css
Chrome DevTools Coverage:
- DevTools → More Tools → Coverage
- Reload page
- Siehe rote Balken = ungenutztes CSS
Präventiv vermeiden
Strategie 1: Utility-First
<!-- Kein Dead CSS möglich -->
<div class="p-4 bg-white rounded shadow">
Strategie 2: CSS-in-JS / CSS Modules
// Nur genutztes CSS wird gebundelt
import styles from './Button.module.css';
<button className={styles.primary}>Click</button>
Strategie 3: Scoped Styles
<!-- Vue: Scoped = nur für diese Komponente -->
<style scoped>
.button { color: blue; }
</style>
Namenskonventionen
/* ✅ Klar wo es genutzt wird */
.home-hero { }
.blog-sidebar { }
.checkout-button { }
/* ❌ Unklar */
.box { }
.content { }
.item { }
4. Theming & Dark Mode
CSS Custom Properties
/* Light Theme (Default) */
:root {
--bg-primary: #ffffff;
--text-primary: #111827;
--border-color: #e5e7eb;
}
/* Dark Theme */
:root[data-theme="dark"] {
--bg-primary: #111827;
--text-primary: #f9fafb;
--border-color: #374151;
}
/* Komponenten nutzen Tokens */
.card {
background: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-color);
}
prefers-color-scheme
/* Automatisch OS-Theme folgen */
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #111827;
--text-primary: #f9fafb;
}
}
Mit User-Override
/* Default: OS folgen */
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
--bg-primary: #111827;
}
}
/* User wählt explizit Light */
:root[data-theme="light"] {
--bg-primary: #ffffff;
}
/* User wählt explizit Dark */
:root[data-theme="dark"] {
--bg-primary: #111827;
}
// Theme-Toggle
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
}
// Initiales Laden
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
setTheme(savedTheme);
}
Performance & Lesbarkeit
❌ Schlecht:
.button {
background: #3b82f6;
color: white;
}
.button-dark {
background: #60a5fa;
color: #111827;
}
✅ Gut:
.button {
background: var(--color-primary);
color: var(--color-on-primary);
}
Vorteil:
- Ein Theme-Toggle ändert alle Komponenten
- Keine Duplikation
- Lesbar
Color-Scheme Property
/* Browser-UI anpassen */
:root {
color-scheme: light dark;
}
/* Form-Controls folgen Theme */
:root[data-theme="dark"] {
color-scheme: dark;
}
Effekt: Scrollbars, Inputs, Checkboxen passen sich an.
KI-Audit: Architektur & Wartbarkeit prüfen
Kopiere diesen Prompt in Claude, ChatGPT oder deine bevorzugte KI:
Analysiere mein Projekt auf CSS-Architektur und Wartbarkeits-Probleme:
1. **Spezifität**: Finde ID-Selektoren (#id) und verschachtelte Selektoren (> 3 Ebenen). Schlage BEM-Alternativen vor.
2. **!important Missbrauch**: Wo wird !important verwendet? Ist es berechtigt (Utilities) oder ein Code-Smell?
3. **@layer Struktur**: Nutze ich @layer? Falls nein, zeige wie ich reset, base, components, utilities organisiere.
4. **Magic Numbers**: Finde hart-codierte Werte (colors, spacing, font-sizes). Schlage Design Tokens via CSS Custom Properties vor.
5. **Duplizierter Code**: Finde wiederkehrende Patterns (gleiche Farben, Abstände, Schatten). Zeige Consolidation-Möglichkeiten.
6. **Dead CSS**: Nutze ich Klassen die nirgends im HTML vorkommen?
7. **Theming**: Prüfe ob Hard-coded Colors existieren die variabel sein sollten (Dark Mode Support).
Gib mir konkrete Refactoring-Vorschläge mit Priorität (kritisch/wichtig/nice-to-have).
Links: