Kurs JavaScript i React · Moduł 14: Zaawansowane stylowanie
CSS Modules - Izolowane Panele Sterowania
W tej lekcji8
CSS Modules to jeden z najpopularniejszych sposobów stylowania w React. Działa jak system izolowanych paneli sterowania na statku kosmicznym -- każdy moduł ma swoje własne kontrolki, które nie kolidują z innymi.
Czym są CSS Modules?
CSS Modules to zwykłe pliki CSS z rozszerzeniem .module.css. Różnica polega na tym, że wszystkie nazwy klas są automatycznie unikalne -- React generuje unikalne identyfikatory, dzięki czemu style z jednego komponentu nigdy nie nadpiszą stylów innego.
1/* SpacePanel.module.css */
2.panel {
3 background: #0d1137;
4 border: 2px solid #3949ab;
5 border-radius: 12px;
6 padding: 20px;
7}
8
9.title {
10 color: #7c4dff;
11 font-size: 24px;
12 margin-bottom: 16px;
13}
14
15.statusActive {
16 color: #00e676;
17 font-weight: bold;
18}Importowanie i używanie
Importujemy CSS Module jako obiekt i odwołujemy się do klas jak do właściwości obiektu:
1import styles from './SpacePanel.module.css';
2
3function SpacePanel({ title, status }) {
4 return (
5 <div className={styles.panel}>
6 <h2 className={styles.title}>{title}</h2>
7 <span className={styles.statusActive}>
8 Status: {status}
9 </span>
10 </div>
11 );
12}W wygenerowanym HTML klasa panel stanie się czymś w stylu SpacePanel_panel_x7k2f -- całkowicie unikalna!
Łączenie klas
Często potrzebujemy łączyć kilka klas CSS. W CSS Modules możemy to robić na kilka sposobów:
1// Template literal
2<div className={`${styles.panel} ${styles.dark}`}>
3
4// Z warunkiem
5<div className={`${styles.panel} ${isActive ? styles.active : ''}`}>
6
7// Tablica z join
8<div className={[styles.panel, styles.dark].join(' ')}>Compose -- dziedziczenie stylów
CSS Modules oferują specjalną dyrektywę composes, która pozwala dziedziczyć style z innych klas:
1/* base.module.css */
2.baseButton {
3 padding: 10px 20px;
4 border: none;
5 border-radius: 6px;
6 cursor: pointer;
7 font-size: 14px;
8 transition: all 0.3s ease;
9}
10
11/* SpaceButton.module.css */
12.primaryButton {
13 composes: baseButton from './base.module.css';
14 background: #7c4dff;
15 color: white;
16}
17
18.dangerButton {
19 composes: baseButton from './base.module.css';
20 background: #f44336;
21 color: white;
22}Dzięki composes unikamy duplikowania stylów, zachowując jednocześnie izolację.
Globalne style w CSS Modules
Jeżeli potrzebujesz klasy globalnej (np. dla zewnętrznych bibliotek), użyj :global:
1/* Layout.module.css */
2:global(.container) {
3 max-width: 1200px;
4 margin: 0 auto;
5}
6
7.localClass {
8 /* To jest lokalne */
9 color: #64b5f6;
10}Dynamiczne klasy z CSS Modules
Często potrzebujemy zmieniać style na podstawie propsów lub stanu. Oto kilka wzorców:
1import styles from './Alert.module.css';
2
3function Alert({ type = 'info', message }) {
4 // Dynamiczne wybieranie klasy na podstawie propsa
5 const alertClass = styles[type]; // styles.info, styles.warning, styles.error
6
7 return (
8 <div className={`${styles.alert} ${alertClass}`}>
9 <p className={styles.message}>{message}</p>
10 </div>
11 );
12}1/* Alert.module.css */
2.alert {
3 padding: 16px;
4 border-radius: 8px;
5 border-left: 4px solid;
6}
7
8.info {
9 background: #1a237e;
10 border-color: #64b5f6;
11 color: #90caf9;
12}
13
14.warning {
15 background: #4a3800;
16 border-color: #ffa726;
17 color: #ffcc80;
18}
19
20.error {
21 background: #4a0000;
22 border-color: #f44336;
23 color: #ef9a9a;
24}Zwróć uwagę, że styles[type] pozwala dynamicznie wybierać klasę na podstawie zmiennej -- to jak przełączanie trybów na panelu sterowania.
Biblioteka classnames / clsx
Do bardziej złożonych kombinacji klas warto używać biblioteki clsx lub classnames:
1import clsx from 'clsx';
2import styles from './Button.module.css';
3
4function SpaceButton({ variant, size, disabled }) {
5 return (
6 <button className={clsx(
7 styles.button,
8 styles[variant], // styles.primary lub styles.secondary
9 styles[size], // styles.small lub styles.large
10 { [styles.disabled]: disabled } // warunkowo
11 )}>
12 Engage!
13 </button>
14 );
15}Zalety CSS Modules
- Izolacja stylów -- brak konfliktów nazw klas, każdy komponent ma swoją "kapsułę"
- Zwykły CSS -- nie trzeba się uczyć nowej składni, używasz tego samego CSS co zawsze
- Wsparcie natywne w Create React App i Next.js -- zero konfiguracji
- Lekkość -- brak dodatkowych bibliotek w bundlu, zero runtime JS
- Łatwa migracja z istniejącego CSS -- wystarczy zmienić rozszerzenie pliku i import
- Typowanie -- można generować typy TypeScript dla klas CSS (np. przez
typed-css-modules)
CSS Modules to solidny, sprawdzony wybór do stylowania komponentów React. Są jak niezawodne panele sterowania na statku -- proste, przewidywalne i bezkonfliktowe.
Kod do tej lekcji: App.jsx
1import React from 'react';
2import styles from './SpacePanel.module.css';
3
4function StatusIndicator({ label, status }) {
5 const statusClass = status === 'active'
6 ? styles.statusActive
7 : status === 'warning'
8 ? styles.statusWarning
9 : styles.statusCritical;
10
11 return (
12 <div className={styles.statusRow}>
13 <span className={styles.label}>{label}</span>
14 <span className={statusClass}>{status.toUpperCase()}</span>
15 </div>
16 );
17}
18
19function SpacePanel({ title, children }) {
20 return (
21 <div className={styles.panel}>
22 <h2 className={styles.title}>{title}</h2>
23 {children}
24 </div>
25 );
26}
27
28export default function App() {
29 return (
30 <div className={styles.app}>
31 <h1 className={styles.heading}>CSS Modules w React</h1>
32 <p className={styles.subtitle}>Izolowane style -- kazdy komponent ma swoje unikalne klasy</p>
33
34 <SpacePanel title="System nawigacyjny">
35 <StatusIndicator label="Silnik glowny" status="active" />
36 <StatusIndicator label="Oslona termiczna" status="warning" />
37 <StatusIndicator label="Paliwo zapasowe" status="critical" />
38 </SpacePanel>
39
40 <SpacePanel title="Komunikacja">
41 <StatusIndicator label="Lacze radiowe" status="active" />
42 <StatusIndicator label="Antena zapasowa" status="active" />
43 <StatusIndicator label="Sygnal SOS" status="active" />
44 </SpacePanel>
45 </div>
46 );
47}Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jaka jest prawidłowa składnia odwołania do CSS Variable w arkuszu stylów?
2. Co jest główną zaletą CSS Modules w porównaniu ze zwykłymi plikami CSS?
Zadania praktyczne w grze
- Edytor kodu
Zaimplementuj komponent AlertBox z CSS Modules
- Klikanie w kolejności
Ułóż składnię importu CSS Module w React:
- Edytor kodu
Zaimplementuj komponent zakładek z CSS Modules i useState