Menu

React CSS: className, Inline Styles, CSS Modules, Tailwind

Du stylst React-Komponenten mit className und gewöhnlichem CSS, mit der style-Prop für Werte, die in JavaScript berechnet werden, mit CSS Modules für gekapselte Klassennamen oder mit Tailwind-Utility-Klassen. Lerne jeden Weg, bedingte Klassen und wann du welchen nimmst.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

React-Komponenten werden mit normalem CSS gestylt. Gib Elementen mit der Prop className eine Klasse und schreibe die Regeln in ein Stylesheet, nutze die Prop style für Werte, die aus JavaScript kommen, und greif zu CSS Modules oder Tailwind, wenn ein Projekt wächst. Das Beispiel unten definiert sein CSS in einem <style>-Element, damit es auf dieser Seite laufen kann; in einem Projekt stünde es in einer .css-Datei.

Ändere in der Regel .btn den Wert #2563eb zu #16a34a, und der Button wird grün. Alles, was du über CSS weißt, gilt: Selektoren, Media Queries, Hover-Zustände, Animationen.

className, nicht class

JSX wird zu JavaScript kompiliert, wo class ein reserviertes Wort ist, also nutzt React className, den Namen, den das DOM selbst für diese Eigenschaft verwendet (element.className). Der Browser erhält trotzdem ein gewöhnliches class-Attribut. Dieselbe Umbenennung gilt für htmlFor statt for an Labels. React 19 akzeptiert class mit einer Warnung in der Entwicklung, aber className ist der korrekte Name und der, den jede Codebasis nutzt.

className nimmt einen String an, also werden mehrere Klassen durch Leerzeichen getrennt: className="btn btn-primary". Weil der Wert JavaScript ist, kann er berechnet werden.

Bedingte Klassen

Um eine Klasse nur in bestimmten Fällen hinzuzufügen, baue den String mit einem ternären Operator oder einem Template-Literal. Eine Tab-Leiste, die den ausgewählten Tab hervorhebt, ist der klassische Fall.

Klicke auf Lessons, und die Unterstreichung wandert, weil jetzt nur der String dieses Buttons active enthält. Reviews bekommt die Klasse disabled und das Attribut disabled, also ist es grau und ignoriert Klicks. Das Template-Literal hinterlässt zusätzliche Leerzeichen, wenn eine Bedingung false ist, die Browser ignorieren. Wenn eine Komponente viele bedingte Klassen hat, ist ein Array ordentlicher:

const classes = ['tab', isActive && 'active', isDisabled && 'disabled']
    .filter(Boolean)
    .join(' ');

Viele Projekte nutzen das winzige Paket clsx für dieselbe Aufgabe: clsx('tab', { active: isActive, disabled: isDisabled }).

Die style-Prop

Die Prop style nimmt ein JavaScript-Objekt an, keinen String. Deshalb hat sie doppelte geschweifte Klammern: Das äußere Paar öffnet einen JavaScript-Ausdruck, das innere ist das Objektliteral. Eigenschaftsnamen sind camelCase (backgroundColor, fontSize, borderRadius), und Werte sind Strings oder Zahlen. Eine Zahl bei einer Längeneigenschaft wird zu Pixeln, also bedeutet padding: 12 gleich 12px.

Inline-Styles glänzen, wenn ein Wert beim Rendern berechnet wird, etwa die Breite eines Fortschrittsbalkens.

Klicke auf Add 10%, bis der Balken voll ist, und er wird grün. Beachte width: percent + '%': Eine nackte Zahl würde Pixel bedeuten, also kommen andere Einheiten als px in einen String. Eigenschaften ohne Einheit bleiben einfache Zahlen, etwa opacity: 0.8, zIndex: 2, flexGrow: 1 und lineHeight: 1.5 (ein Faktor, keine Pixel).

Inline-Styles haben Grenzen. Sie können kein :hover, :focus, keine Media Queries und keine Keyframe-Animationen ausdrücken, und jedes Element trägt seine eigene Kopie der Regeln. Nutze sie für die dynamischen Werte und lass den Rest im CSS.

CSS-Variablen aus Props

Ein guter Mittelweg ist, in style eine CSS Custom Property zu setzen und sie in deinem Stylesheet zu verwenden. Die Regeln bleiben im CSS, Hover-Zustände eingeschlossen, und nur der Wert kommt aus JavaScript.

Wähle eine neue Farbe, und beide Buttons folgen ihr, und die Hover-Füllung funktioniert weiterhin, weil sie reines CSS ist. Namen von Custom Properties behalten im style-Objekt ihre Bindestriche, also kommen sie in Anführungszeichen: { '--accent': accent }.

CSS-Dateien

In einem echten Projekt schreibst du Styles in .css-Dateien und importierst sie aus der Komponente, die sie braucht. Mit Vite reicht der Import: Das Build-Tool sieht import './Button.css', fügt das Stylesheet in der Entwicklung der Seite hinzu und bündelt es für die Produktion in eine CSS-Datei. Es gibt keinen Export zu nutzen; der Import existiert nur wegen seines Nebeneffekts.

// Button.jsx
import './Button.css';

export default function Button({ children }) {
    return <button className="button">{children}</button>;
}
/* Button.css */
.button {
    background: #2563eb;
    color: white;
    border-radius: 6px;
}

Der Haken: Jedes importierte Stylesheet ist global. Eine Regel .button in Button.css stylt jedes Element mit dieser Klasse, überall in der App, und zwei Dateien, die beide .title definieren, überschreiben sich gegenseitig. Teams lösen das mit Namenskonventionen wie BEM (.card__title) oder mit CSS Modules.

CSS Modules

Eine Datei mit der Endung .module.css ist ein CSS Module. Wenn du sie importierst, bekommst du ein Objekt, das jeden geschriebenen Klassennamen einem eindeutigen generierten Namen zuordnet, also gilt eine Klasse nur dort, wo du sie verwendest. Vite und Next.js unterstützen das ohne Setup.

// Card.jsx
import styles from './Card.module.css';

export default function Card({ title, children, featured }) {
    return (
        <section className={featured ? `${styles.card} ${styles.featured}` : styles.card}>
            <h3 className={styles.title}>{title}</h3>
            {children}
        </section>
    );
}
/* Card.module.css */
.card { border: 1px solid #ddd; border-radius: 10px; padding: 16px; }
.featured { border-color: #2563eb; }
.title { margin: 0; }

Im Browser erscheint die Klasse als etwas wie _card_1x2ab_1. Eine andere Komponente kann ihr eigenes .title definieren, und die beiden kollidieren nie. Du schreibst normales CSS, Hover-Regeln und Media Queries eingeschlossen, deshalb sind CSS Modules ein üblicher Standard für Komponenten-Styles.

Tailwind CSS mit React

Tailwind geht einen anderen Weg: Statt Regeln zu schreiben, setzt du kleine Utility-Klassen direkt in className zusammen. px-4 setzt das horizontale Padding, rounded-lg rundet die Ecken, hover:bg-blue-700 ändert beim Hover den Hintergrund. Tailwind durchsucht deine Dateien und erzeugt CSS nur für die Klassen, die du nutzt.

Die Einrichtung in einer Vite-React-App (Tailwind v4) braucht drei Schritte:

npm install tailwindcss @tailwindcss/vite
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
    plugins: [react(), tailwindcss()],
});
/* src/index.css, imported from main.jsx */
@import "tailwindcss";

Dann stylst du Komponenten mit Klassen:

function UpgradeCard({ active }) {
    return (
        <div className="max-w-xs rounded-xl border border-gray-200 p-4">
            <h3 className="mb-2 text-lg font-semibold">Pro plan</h3>
            <button
                className={`rounded-md px-4 py-2 text-white ${active ? 'bg-green-600' : 'bg-blue-600 hover:bg-blue-700'}`}
            >
                {active ? 'Active' : 'Upgrade'}
            </button>
        </div>
    );
}

In den Editoren auf dieser Seite ist Tailwind nicht verfügbar, deshalb wird es als statischer Code gezeigt. Bedingte Klassen funktionieren genau wie im Tab-Beispiel oben, aber schreib jeden Klassennamen vollständig aus: Tailwind findet Klassen, indem es deinen Quelltext durchsucht, also wird ein zur Laufzeit zusammengesetzter Name wie `bg-${color}-600` nie erzeugt.

Wann du was nimmst

  • Reine CSS-Dateien passen zu kleinen Apps und globalen Styles (Resets, Schriften, Seitenlayout). Achte auf kollidierende Klassennamen, wenn die App wächst.
  • CSS Modules passen zu den meisten Komponenten-Styles: normales CSS, automatisch gekapselt, keine zusätzliche Bibliothek.
  • Tailwind passt zu Teams, die lieber im Markup stylen und eine gemeinsame Designskala für Abstände und Farben wollen.
  • Die Prop style ist für Werte, die beim Rendern berechnet werden: eine Breite, eine Position, eine vom Nutzer gewählte Farbe. Kombiniere sie mit CSS-Variablen, um Hover- und Media-Regeln im CSS zu halten.

Du kannst sie mischen. Eine typische App hat ein globales Stylesheet, CSS Modules oder Tailwind für Komponenten und ein paar Inline-Styles für dynamische Werte. CSS-in-JS-Bibliotheken wie styled-components und Emotion sind eine weitere Option, die dir in älteren Codebasen begegnet. Die Seite zum Installieren von React zeigt, wie du ein Vite-Projekt startest, in dem all das funktioniert.

Häufig gestellte Fragen

Warum nutzt React className statt class?

JSX wird zu JavaScript kompiliert, und dort ist class ein reserviertes Wort. React nutzt den Namen der DOM-Eigenschaft, className, so heißt element.className auch in reinem JavaScript. Im HTML wird daraus trotzdem ein normales class-Attribut.

Wie schreibe ich Inline-Styles in React?

Übergib der Prop style ein Objekt mit Eigenschaftsnamen in camelCase: style={{ backgroundColor: 'teal', fontSize: 18 }}. Die äußeren geschweiften Klammern öffnen einen JavaScript-Ausdruck, die inneren sind das Objekt. Zahlen werden bei Eigenschaften mit Längenangabe zu Pixeln.

Wie füge ich in React eine Klasse bedingt hinzu?

Bau den String in JavaScript: className={isActive ? 'tab active' : 'tab'} oder ein Template-Literal wie className={`tab ${isActive ? 'active' : ''}`}. Bei vielen Bedingungen hält ein kleiner Helfer wie das Paket clsx das lesbar.

Sind CSS-Dateien in React global?

Ja. import './App.css' fügt das Stylesheet der ganzen Seite hinzu, also können seine Klassennamen mit anderen Dateien kollidieren. CSS Modules (App.module.css) benennen jede Klasse in einen eindeutigen Namen um, damit sie nur dort gilt, wo du sie importierst.

Wie nutze ich Tailwind mit React?

Installiere in einem Vite-Projekt tailwindcss und @tailwindcss/vite, füge das Plugin in vite.config.js hinzu und setze @import "tailwindcss"; an den Anfang deiner Haupt-CSS-Datei. Dann schreibst du Utility-Klassen in className, etwa className="px-4 py-2 rounded bg-blue-600 text-white".

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

LOS GEHT'S