CSS Modules & Styled Components
Lerne CSS Modules und Styled Components kennen - zwei populäre Ansätze für komponentenbasiertes Styling ohne Namenskonflikte.
CSS Modules & Styled Components
In groesseren React-Projekten fuehrt klassisches CSS schnell zu Namenskonflikten. CSS Modules und Styled Components loesen dieses Problem auf elegante Weise. In diesem Tutorial lernst du beide Ansaetze kennen.
CSS Modules
CSS Modules sind CSS-Dateien mit lokalem Scope. Jede Klasse wird automatisch eindeutig umbenannt, sodass keine Konflikte entstehen.
Wie es funktioniert
Erstelle eine Datei mit der Endung .module.css:
/* Button.module.css */
.button {
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
transition: all 0.2s;
}
.primary {
background-color: #3498db;
color: white;
}
.primary:hover {
background-color: #2980b9;
}
.secondary {
background-color: #ecf0f1;
color: #2c3e50;
}
.secondary:hover {
background-color: #d5dbdb;
}
.large {
padding: 14px 28px;
font-size: 1.125rem;
}
// Button.jsx
import styles from './Button.module.css';
function Button({ variant = 'primary', size, children, onClick }) {
const className = [
styles.button,
styles[variant],
size === 'large' && styles.large
].filter(Boolean).join(' ');
return (
<button className={className} onClick={onClick}>
{children}
</button>
);
}
export default Button;
Was passiert unter der Haube?
/* Im Browser wird daraus: */
.Button_button_x7yz3 { /* ... */ }
.Button_primary_a2bc4 { /* ... */ }
Die Klassen werden automatisch umbenannt – Konflikte sind unmoeglich!
Vorteile von CSS Modules
| Vorteil | Beschreibung |
|---|---|
| Lokaler Scope | Klassen gelten nur in der Komponente |
| Keine Konflikte | Eindeutige Klassennamen |
| Standard-CSS | Keine neue Syntax zu lernen |
| Vite-Support | Funktioniert out of the box |
| IDE-Support | Autovervollstaendigung moeglich |
Komplexeres Beispiel: Card-Komponente
/* Card.module.css */
.card {
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.image {
width: 100%;
height: 200px;
object-fit: cover;
}
.content {
padding: 1.25rem;
}
.title {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: 0.5rem;
color: #1a1a1a;
}
.description {
color: #666;
line-height: 1.5;
margin-bottom: 1rem;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.25rem;
border-top: 1px solid #eee;
}
.price {
font-size: 1.5rem;
font-weight: 700;
color: #2563eb;
}
// Card.jsx
import styles from './Card.module.css';
function Card({ image, title, description, price, onBuy }) {
return (
<div className={styles.card}>
<img className={styles.image} src={image} alt={title} />
<div className={styles.content}>
<h3 className={styles.title}>{title}</h3>
<p className={styles.description}>{description}</p>
</div>
<div className={styles.footer}>
<span className={styles.price}>{price} Euro</span>
<button onClick={onBuy}>Kaufen</button>
</div>
</div>
);
}
Globale Klassen in CSS Modules
Manchmal brauchst du globale Klassen:
/* Globale Klasse innerhalb eines Modules */
:global(.visually-hidden) {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
}
/* Compose: Klassen zusammensetzen */
.error {
composes: button;
background-color: #e74c3c;
}
Styled Components
Styled Components ist eine CSS-in-JS-Bibliothek, bei der du Styles direkt in JavaScript schreibst:
npm install styled-components
Grundlegende Verwendung
import styled from 'styled-components';
const StyledButton = styled.button`
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
background-color: #3498db;
color: white;
transition: background-color 0.2s;
&:hover {
background-color: #2980b9;
}
`;
function App() {
return <StyledButton>Klick mich</StyledButton>;
}
Dynamische Styles mit Props
const Button = styled.button`
padding: ${props => props.size === 'large' ? '14px 28px' : '10px 20px'};
font-size: ${props => props.size === 'large' ? '1.125rem' : '1rem'};
background-color: ${props => {
switch (props.variant) {
case 'danger': return '#e74c3c';
case 'success': return '#27ae60';
default: return '#3498db';
}
}};
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
&:hover {
opacity: 0.9;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
// Verwendung
<Button variant="danger" size="large">Loeschen</Button>
<Button variant="success">Speichern</Button>
<Button disabled>Deaktiviert</Button>
Styles erweitern
const BaseButton = styled.button`
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
`;
const PrimaryButton = styled(BaseButton)`
background-color: #3498db;
color: white;
`;
const OutlineButton = styled(BaseButton)`
background-color: transparent;
border: 2px solid #3498db;
color: #3498db;
`;
Theme-Provider
Styled Components hat ein eingebautes Theme-System:
import { ThemeProvider } from 'styled-components';
const lightTheme = {
colors: {
primary: '#3498db',
background: '#ffffff',
text: '#333333',
border: '#e5e7eb'
},
spacing: {
sm: '0.5rem',
md: '1rem',
lg: '2rem'
}
};
const darkTheme = {
colors: {
primary: '#60a5fa',
background: '#1a1a2e',
text: '#e0e0e0',
border: '#374151'
},
spacing: lightTheme.spacing
};
const Card = styled.div`
background: ${props => props.theme.colors.background};
color: ${props => props.theme.colors.text};
border: 1px solid ${props => props.theme.colors.border};
padding: ${props => props.theme.spacing.lg};
border-radius: 12px;
`;
function App() {
const [isDark, setIsDark] = useState(false);
return (
<ThemeProvider theme={isDark ? darkTheme : lightTheme}>
<Card>
<h2>Theme-Beispiel</h2>
<button onClick={() => setIsDark(!isDark)}>Theme wechseln</button>
</Card>
</ThemeProvider>
);
}
CSS Modules vs. Styled Components
| Kriterium | CSS Modules | Styled Components |
|---|---|---|
| Syntax | Standard-CSS | CSS-in-JS |
| Dynamische Styles | Mit Klassen-Toggle | Direkt mit Props |
| Bundle-Groesse | Kein Extra-JS | ~12 KB gzipped |
| Lernkurve | Niedrig | Mittel |
| DevTools | Echte CSS-Klassen | Generierte Klassen |
| Performance | Sehr gut | Gut |
| Server Rendering | Einfach | Braucht Setup |
Empfehlung fuer Einsteiger
- Starte mit CSS Modules – einfach, performant, keine Abhaengigkeiten
- Nutze Styled Components wenn du viele dynamische Styles brauchst
- Erwaege Tailwind CSS fuer schnelle Prototypen und Utility-First-Ansatz
Uebungen
- Baue eine Card-Komponente mit CSS Modules inklusive Hover-Effekt und verschiedener Varianten
- Erstelle ein Button-System mit Styled Components mit Primary, Secondary und Danger-Varianten
- Implementiere einen Dark-Mode mit dem Theme-Provider von Styled Components
Was kommt als Naechstes?
Du kennst jetzt CSS Modules und Styled Components. Im naechsten Kapitel lernst du UI-Bibliotheken wie Material UI und Chakra UI kennen – fertige Komponentenbibliotheken, die dir eine Menge Styling-Arbeit abnehmen.
Zusammenfassung
- CSS Modules generieren eindeutige Klassen automatisch – keine Namenskonflikte
- Dateien enden auf
.module.cssund werden als Objekt importiert - Styled Components schreiben CSS direkt in JavaScript mit Template Literals
- Styled Components unterstuetzen dynamische Styles basierend auf Props
- CSS Modules sind leichtgewichtiger, Styled Components flexibler
- Beide Ansaetze eliminieren das Problem globaler CSS-Konflikte
Pro-Tipp: Mische nicht zu viele Styling-Ansaetze in einem Projekt. Entscheide dich fuer einen Hauptansatz (CSS Modules ODER Styled Components ODER Tailwind) und bleibe dabei. Konsistenz ist wichtiger als die “perfekte” Loesung!