CSS in React
Lerne die verschiedenen Möglichkeiten, React-Komponenten zu stylen. Von klassischem CSS über Inline-Styles bis hin zu modernen Ansätzen.
CSS in React
Styling ist ein wesentlicher Teil jeder React-App. Es gibt viele Wege, Komponenten zu stylen – jeder mit eigenen Vor- und Nachteilen. In diesem Tutorial lernst du die gaengigsten Methoden kennen.
Ueberblick: Styling-Methoden
| Methode | Scope | Dynamisch | Beliebt |
|---|---|---|---|
| Klassisches CSS | Global | Nein | Ja |
| Inline-Styles | Komponente | Ja | Mittel |
| CSS Modules | Komponente | Nein | Ja |
| CSS-in-JS (Styled Components) | Komponente | Ja | Ja |
| Tailwind CSS | Utility-Klassen | Ja | Sehr hoch |
Klassisches CSS
Der einfachste Ansatz – eine CSS-Datei importieren:
/* Button.css */
.button {
padding: 8px 16px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.2s;
}
.button-primary {
background-color: #3498db;
color: white;
}
.button-primary:hover {
background-color: #2980b9;
}
.button-danger {
background-color: #e74c3c;
color: white;
}
.button-danger:hover {
background-color: #c0392b;
}
// Button.jsx
import './Button.css';
function Button({ variant = 'primary', children, onClick }) {
return (
<button
className={`button button-${variant}`}
onClick={onClick}
>
{children}
</button>
);
}
Dynamische Klassen
function NavLink({ href, isActive, children }) {
// Klassen bedingt zusammensetzen
const className = `nav-link ${isActive ? 'nav-link-active' : ''}`;
return <a href={href} className={className}>{children}</a>;
}
// Oder mit Template Literals
function Card({ featured }) {
return (
<div className={`card ${featured ? 'card-featured' : ''}`}>
Inhalt
</div>
);
}
Mehrere Klassen zusammensetzen
function Alert({ type, dismissible, className = '' }) {
const classes = [
'alert',
`alert-${type}`,
dismissible && 'alert-dismissible',
className
].filter(Boolean).join(' ');
return <div className={classes}>Nachricht</div>;
}
Inline-Styles
Styles direkt als JavaScript-Objekt:
function StyledCard({ highlighted }) {
const cardStyle = {
padding: '1.5rem',
borderRadius: '12px',
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
backgroundColor: highlighted ? '#fffbeb' : '#ffffff',
border: highlighted ? '2px solid #f59e0b' : '1px solid #e5e7eb',
transition: 'all 0.2s ease'
};
return (
<div style={cardStyle}>
<h3 style={{ margin: '0 0 0.5rem', color: '#1f2937' }}>Titel</h3>
<p style={{ margin: 0, color: '#6b7280' }}>Beschreibung hier.</p>
</div>
);
}
Vorteile und Nachteile
| Vorteile | Nachteile |
|---|---|
| Dynamisch basierend auf Props/State | Keine Pseudo-Selektoren (:hover, :focus) |
| Kein Klassen-Namenskonflikt | Keine Media Queries |
| Inline = nah am Code | Keine Animationen (@keyframes) |
| Performance bei vielen Elementen |
Dynamische Styles
function ProgressBar({ progress }) {
return (
<div style={{
width: '100%',
height: '20px',
backgroundColor: '#e5e7eb',
borderRadius: '10px',
overflow: 'hidden'
}}>
<div style={{
width: `${Math.min(100, Math.max(0, progress))}%`,
height: '100%',
backgroundColor: progress >= 100 ? '#10b981' :
progress >= 50 ? '#3b82f6' : '#f59e0b',
transition: 'width 0.3s ease, background-color 0.3s ease',
borderRadius: '10px'
}} />
</div>
);
}
CSS-Klassen mit clsx/classnames
Die Bibliothek clsx macht das Zusammensetzen von Klassen elegant:
npm install clsx
import clsx from 'clsx';
function Button({ variant, size, disabled, fullWidth, children }) {
const className = clsx(
'btn',
`btn-${variant}`,
`btn-${size}`,
{
'btn-disabled': disabled,
'btn-full': fullWidth
}
);
return <button className={className}>{children}</button>;
}
// Ergebnis: "btn btn-primary btn-large btn-full"
<Button variant="primary" size="large" fullWidth>Weiter</Button>
Globale Styles vs. Komponenten-Styles
Globale Styles (index.css)
/* index.css - Globale Styles */
:root {
--color-primary: #3498db;
--color-danger: #e74c3c;
--color-success: #27ae60;
--border-radius: 8px;
--font-family: 'Inter', sans-serif;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-family);
line-height: 1.6;
color: #333;
}
Komponenten-Styles
/* Header.css - Nur fuer die Header-Komponente */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background-color: var(--color-primary);
color: white;
}
.header-logo {
font-size: 1.5rem;
font-weight: bold;
}
.header-nav a {
color: white;
text-decoration: none;
margin-left: 1rem;
}
Responsive Design
/* Responsive.css */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
.grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 1rem;
}
@media (min-width: 640px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
.grid { grid-template-columns: repeat(3, 1fr); }
}
function ProductGrid({ products }) {
return (
<div className="container">
<div className="grid">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
</div>
);
}
Praktisches Beispiel: Navigationsleiste
/* Navbar.css */
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 2rem;
background: white;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 100;
}
.navbar-brand {
font-size: 1.25rem;
font-weight: 700;
color: #3498db;
text-decoration: none;
}
.navbar-links {
display: flex;
gap: 1.5rem;
list-style: none;
}
.navbar-link {
color: #555;
text-decoration: none;
padding: 0.5rem 0;
border-bottom: 2px solid transparent;
transition: all 0.2s;
}
.navbar-link:hover,
.navbar-link-active {
color: #3498db;
border-bottom-color: #3498db;
}
import './Navbar.css';
function Navbar({ currentPage }) {
const links = [
{ href: '/', label: 'Home' },
{ href: '/about', label: 'Ueber uns' },
{ href: '/contact', label: 'Kontakt' }
];
return (
<nav className="navbar">
<a href="/" className="navbar-brand">MeineApp</a>
<ul className="navbar-links">
{links.map(link => (
<li key={link.href}>
<a
href={link.href}
className={`navbar-link ${
currentPage === link.href ? 'navbar-link-active' : ''
}`}
>
{link.label}
</a>
</li>
))}
</ul>
</nav>
);
}
Uebungen
- Style eine Card-Komponente mit CSS-Datei, die auf Hover einen Schatten-Effekt bekommt
- Erstelle eine ProgressBar mit Inline-Styles und dynamischer Breite basierend auf Props
- Baue ein responsives Grid-Layout mit CSS Grid, das auf Mobile eine Spalte und auf Desktop drei Spalten zeigt
Was kommt als Naechstes?
Du kennst jetzt die Grundlagen von CSS in React. Im naechsten Kapitel lernst du CSS Modules und Styled Components kennen – fortgeschrittene Methoden, die Styling-Konflikte eliminieren und komponentenbasiertes Styling ermoeglichen.
Zusammenfassung
- Klassisches CSS ist einfach und bewaehrt, aber Klassen sind global
- Inline-Styles sind dynamisch, unterstuetzen aber keine Pseudo-Selektoren
- Nutze CSS-Variablen fuer konsistente Farben und Groessen
- clsx vereinfacht das Zusammensetzen dynamischer Klassen
- Trenne globale Styles (Reset, Variablen) von Komponenten-Styles
Pro-Tipp: Nutze CSS Custom Properties (Variablen) fuer dein Design-System. Definiere Farben, Abstands-Stufen und Schriftgroessen als Variablen in :root und verwende sie ueberall. So kannst du das gesamte Design an einer Stelle aendern – und ein Dark-Mode wird zum Kinderspiel!