Zum Inhalt springen
React Anfänger 25 min

CSS in React

Lerne die verschiedenen Möglichkeiten, React-Komponenten zu stylen. Von klassischem CSS über Inline-Styles bis hin zu modernen Ansätzen.

Aktualisiert:

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

MethodeScopeDynamischBeliebt
Klassisches CSSGlobalNeinJa
Inline-StylesKomponenteJaMittel
CSS ModulesKomponenteNeinJa
CSS-in-JS (Styled Components)KomponenteJaJa
Tailwind CSSUtility-KlassenJaSehr 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

VorteileNachteile
Dynamisch basierend auf Props/StateKeine Pseudo-Selektoren (:hover, :focus)
Kein Klassen-NamenskonfliktKeine Media Queries
Inline = nah am CodeKeine 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

  1. Style eine Card-Komponente mit CSS-Datei, die auf Hover einen Schatten-Effekt bekommt
  2. Erstelle eine ProgressBar mit Inline-Styles und dynamischer Breite basierend auf Props
  3. 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!

Zurück zum React Kurs