Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Globalne style i CSS Modules w Next.js 15

Witaj w Metropolis Quantum, mieście przyszłości, gdzie każdy element przestrzeni miejskiej ma swój własny, unikalny styl, a jednocześnie całe miasto utrzymuje spójną estetykę. Podobnie jak w tym futurystycznym mieście, w aplikacjach Next.js 15 potrzebujemy zarówno globalnych reguł stylowania, które definiują ogólny wygląd, jak i lokalnych, modułowych stylów, które zapobiegają konfliktom i pozwalają na utrzymanie porządku.

W tym rozdziale poznamy dwa kluczowe podejścia do stylowania w Next.js 15:

  1. Style globalne - wpływające na całą aplikację
  2. CSS Modules - pozwalające na lokalne, hermetyczne stylowanie komponentów

Style globalne w Next.js 15

W Metropolis Quantum podstawowe elementy infrastruktury, takie jak system transportu, oświetlenie czy oznakowanie, mają jednolity wygląd w całym mieście. Podobnie, w aplikacjach webowych potrzebujemy globalnych reguł stylowania dla podstawowych elementów, takich jak typografia, kolory, marginesy czy siatka.

Plik global.css

W Next.js 15 globalne style są najczęściej definiowane w pliku

app/globals.css
, który następnie jest importowany w głównym layoucie aplikacji. Tak wygląda typowa struktura:

1// app/layout.tsx
2import './globals.css';
3import type { Metadata } from 'next';
4
5export const metadata: Metadata = {
6  title: 'Metropolis Quantum',
7  description: 'Twoja brama do miasta przyszłości',
8};
9
10export default function RootLayout({
11  children,
12}: {
13  children: React.ReactNode;
14}) {
15  return (
16    <html lang="pl">
17      <body>{children}</body>
18    </html>
19  );
20}

Zawartość pliku

globals.css
może wyglądać tak:

1/* app/globals.css */
2:root {
3  --primary-color: #3a86ff;
4  --secondary-color: #8338ec;
5  --accent-color: #ff006e;
6  --background-light: #f8f9fa;
7  --background-dark: #212529;
8  --text-light: #f8f9fa;
9  --text-dark: #212529;
10  --spacing-unit: 0.5rem;
11  --border-radius: 0.375rem;
12}
13
14* {
15  box-sizing: border-box;
16  padding: 0;
17  margin: 0;
18}
19
20html,
21body {
22  max-width: 100vw;
23  overflow-x: hidden;
24  font-family: 'Quantum Sans', sans-serif;
25}
26
27body {
28  color: var(--text-dark);
29  background: var(--background-light);
30}
31
32a {
33  color: var(--primary-color);
34  text-decoration: none;
35}
36
37h1, h2, h3, h4, h5, h6 {
38  font-family: 'Quantum Display', sans-serif;
39  margin-bottom: var(--spacing-unit);
40}
41
42.container {
43  width: 100%;
44  max-width: 1200px;
45  margin: 0 auto;
46  padding: 0 var(--spacing-unit);
47}
48
49@media (prefers-color-scheme: dark) {
50  body {
51    color: var(--text-light);
52    background: var(--background-dark);
53  }
54}

CSS Reset i Normalizacja

Często dobrą praktyką jest rozpoczęcie od tzw. CSS Reset lub normalizacji, które niwelują różnice między domyślnymi stylami różnych przeglądarek. Możesz użyć popularnych rozwiązań, takich jak:

  • normalize.css
  • reset.css
  • Własne rozwiązanie

Przykładowo, można zainstalować

normalize.css
za pomocą npm i zaimportować go na początku pliku globals.css:

1npm install normalize.css
1/* app/globals.css */
2@import 'normalize.css';
3
4/* Reszta globalnych stylów */

Wykorzystanie zmiennych CSS

Jak widać w powyższym przykładzie, zmienne CSS (custom properties) są potężnym narzędziem do definiowania globalnych wartości, które można następnie wykorzystać w całej aplikacji:

1:root {
2  --primary-color: #3a86ff;
3  --spacing-large: 2rem;
4}
5
6.button {
7  background-color: var(--primary-color);
8  padding: var(--spacing-large);
9}

To podejście pozwala na łatwe zarządzanie paletą kolorów, odstępami, rozmiarami czcionek i innymi powtarzającymi się wartościami.

Globalne style dla określonych ścieżek

W Next.js 15 możesz również definiować style globalne, które będą stosowane tylko do określonych ścieżek lub layoutów. Służą do tego pliki

layout.tsx
w poszczególnych katalogach:

1// app/dashboard/layout.tsx
2import '../dashboard-styles.css';
3
4export default function DashboardLayout({
5  children,
6}: {
7  children: React.ReactNode;
8}) {
9  return <div className="dashboard-container">{children}</div>;
10}

Te style będą stosowane tylko do stron wewnątrz katalogu

/dashboard
.

CSS Modules: Hermetyzacja stylów

W Metropolis Quantum każda dzielnica ma swoją unikalną estetykę - Dystrykt Kwantowy pełen jest futurystycznych, holograficznych elementów, podczas gdy Stare Miasto łączy nowoczesność z architekturą retro. Mimo tych różnic, wszystkie dzielnice stanowią spójną całość.

CSS Modules działa podobnie - pozwala na tworzenie lokalnych, hermetycznych stylów dla komponentów, które nie będą wpływać na resztę aplikacji.

Podstawy CSS Modules

CSS Modules to technika, która automatycznie tworzy unikalne nazwy klas CSS, zapobiegając konfliktom. W Next.js 15 każdy plik z rozszerzeniem

.module.css
jest traktowany jako moduł CSS.

Tworzenie i używanie modułu CSS:

1/* Button.module.css */
2.button {
3  padding: 0.75rem 1.5rem;
4  border-radius: 0.375rem;
5  font-weight: 600;
6  transition: all 0.2s;
7}
8
9.primary {
10  background-color: var(--primary-color);
11  color: white;
12}
13
14.secondary {
15  background-color: var(--secondary-color);
16  color: white;
17}
18
19.button:hover {
20  transform: translateY(-2px);
21  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
22}
1// components/Button.tsx
2import styles from './Button.module.css';
3
4interface ButtonProps {
5  variant?: 'primary' | 'secondary';
6  children: React.ReactNode;
7  onClick?: () => void;
8}
9
10export default function Button({ variant = 'primary', children, onClick }: ButtonProps) {
11  return (
12    <button 
13      className={`${styles.button} ${styles[variant]}`}
14      onClick={onClick}
15    >
16      {children}
17    </button>
18  );
19}

Jak działają CSS Modules

Gdy aplikacja jest budowana, Next.js przetwarza pliki

.module.css
i generuje unikalne nazwy klas. Na przykład, klasa
.button
z powyższego przykładu może zostać przekształcona w
.Button_button__XYZ123
. Dzięki temu, nawet jeśli w innym komponencie zdefiniujesz klasę o tej samej nazwie, nie dojdzie do konfliktu.

Dostęp do globalnych zmiennych CSS

CSS Modules mogą korzystać z globalnych zmiennych CSS zdefiniowanych w

globals.css
:

1/* Card.module.css */
2.card {
3  background-color: white;
4  border-radius: var(--border-radius);
5  padding: calc(var(--spacing-unit) * 2);
6  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
7}

Komponowanie klas

CSS Modules pozwala na komponowanie klas za pomocą składni

composes
:

1/* Text.module.css */
2.base {
3  font-family: 'Quantum Sans', sans-serif;
4  line-height: 1.5;
5}
6
7.heading {
8  composes: base;
9  font-weight: 700;
10  line-height: 1.2;
11}
12
13.paragraph {
14  composes: base;
15  margin-bottom: 1rem;
16}

Dynamiczne style z CSS Modules

Możesz dynamicznie stosować klasy w zależności od stanu komponentu:

1// components/Alert.tsx
2import { useState } from 'react';
3import styles from './Alert.module.css';
4
5interface AlertProps {
6  type: 'info' | 'success' | 'warning' | 'error';
7  message: string;
8}
9
10export default function Alert({ type, message }: AlertProps) {
11  const [isVisible, setIsVisible] = useState(true);
12
13  if (!isVisible) return null;
14
15  return (
16    <div className={`${styles.alert} ${styles[type]} ${isVisible ? styles.visible : ''}`}>
17      <p>{message}</p>
18      <button 
19        className={styles.closeButton}
20        onClick={() => setIsVisible(false)}
21      >
22        &times;
23      </button>
24    </div>
25  );
26}
1/* Alert.module.css */
2.alert {
3  padding: 1rem;
4  border-radius: var(--border-radius);
5  margin-bottom: 1rem;
6  display: flex;
7  justify-content: space-between;
8  align-items: center;
9}
10
11.info {
12  background-color: #e3f2fd;
13  color: #0d47a1;
14}
15
16.success {
17  background-color: #e8f5e9;
18  color: #1b5e20;
19}
20
21.warning {
22  background-color: #fff3e0;
23  color: #e65100;
24}
25
26.error {
27  background-color: #ffebee;
28  color: #b71c1c;
29}
30
31.visible {
32  opacity: 1;
33  transition: opacity 0.3s ease-in;
34}
35
36.closeButton {
37  background: none;
38  border: none;
39  font-size: 1.5rem;
40  cursor: pointer;
41  opacity: 0.7;
42}
43
44.closeButton:hover {
45  opacity: 1;
46}

Łączenie globalnych stylów z CSS Modules

W rzeczywistych aplikacjach najczęściej stosuje się oba podejścia:

  1. Globalne style dla:

    • Resetowania CSS
    • Podstawowych elementów typografii
    • Zmiennych (kolory, odstępy, cienie, itp.)
    • Klas użytkowych (utilities)
  2. CSS Modules dla:

    • Konkretnych komponentów
    • Elementów, które mogą mieć różne style w zależności od kontekstu

Przykład: Struktura projektu

1app/
2├── layout.tsx
3├── page.tsx
4├── globals.css
5├── dashboard/
6│   ├── layout.tsx
7│   ├── page.tsx
8│   └── dashboard.module.css
9└── components/
10    ├── Button/
11    │   ├── Button.tsx
12    │   └── Button.module.css
13    ├── Card/
14    │   ├── Card.tsx
15    │   └── Card.module.css
16    └──

Alternatywne podejścia do stylowania w Next.js 15

Oprócz globalnych stylów i CSS Modules, Next.js 15 wspiera również inne podejścia do stylowania:

1. Styled JSX

Next.js ma wbudowane wsparcie dla Styled JSX, które pozwala na tworzenie stylów lokalnych bezpośrednio w komponentach:

1export default function Button() {
2  return (
3    <>
4      <button>Kliknij mnie</button>
5      <style jsx>{`
6        button {
7          padding: 0.5rem 1rem;
8          background-color: #3a86ff;
9          color: white;
10          border: none;
11          border-radius: 0.25rem;
12        }
13        button:hover {
14          background-color: #2563eb;
15        }
16      `}</style>
17    </>
18  );
19}

2. Sass/SCSS

Next.js wspiera również Sass/SCSS. Wystarczy zainstalować

sass
:

1npm install sass

Następnie możesz tworzyć pliki

.scss
lub
.sass
, w tym moduły CSS z rozszerzeniem
.module.scss
:

1// Button.module.scss
2$primary-color: #3a86ff;
3
4.button {
5  padding: 0.75rem 1.5rem;
6  background-color: $primary-color;
7  
8  &:hover {
9    background-color: darken($primary-color, 10%);
10  }
11  
12  .icon {
13    margin-right: 0.5rem;
14  }
15}

3. CSS-in-JS

Next.js wspiera również biblioteki CSS-in-JS, takie jak

styled-components
czy
emotion
. W przypadku tych bibliotek, potrzebne jest dodatkowe ustawienie, aby działały z SSR (Server-Side Rendering):

1// components/StyledButton.tsx
2import styled from 'styled-components';
3
4const StyledButton = styled.button`
5  padding: 0.75rem 1.5rem;
6  background-color: #3a86ff;
7  color: white;
8  border: none;
9  border-radius: 0.25rem;
10  
11  &:hover {
12    background-color: #2563eb;
13  }
14`;
15
16export default function Button({ children }) {
17  return <StyledButton>{children}</StyledButton>;
18}

Aby

styled-components
działały z SSR, musisz utworzyć własny dokument w Next.js:

1// app/registry.tsx
2'use client';
3
4import { useState } from 'react';
5import { useServerInsertedHTML } from 'next/navigation';
6import { ServerStyleSheet, StyleSheetManager } from 'styled-components';
7
8export default function StyledComponentsRegistry({
9  children,
10}: {
11  children: React.ReactNode;
12}) {
13  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());
14
15  useServerInsertedHTML(() => {
16    const styles = styledComponentsStyleSheet.getStyleElement();
17    styledComponentsStyleSheet.instance.clearTag();
18    return <>{styles}</>;
19  });
20
21  if (typeof window !== 'undefined') return <>{children}</>;
22
23  return (
24    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
25      {children}
26    </StyleSheetManager>
27  );
28}
1// app/layout.tsx
2import StyledComponentsRegistry from './registry';
3import './globals.css';
4
5export default function RootLayout({
6  children,
7}: {
8  children: React.ReactNode;
9}) {
10  return (
11    <html>
12      <body>
13        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
14      </body>
15    </html>
16  );
17}

Praktyczne przykłady

Przykład 1: Tworzenie systemu siatki (grid)

1/* app/globals.css */
2.row {
3  display: flex;
4  flex-wrap: wrap;
5  margin: 0 -1rem;
6}
7
8.col {
9  padding: 0 1rem;
10}
11
12.col-1 { flex: 0 0 8.333%; max-width: 8.333%; }
13.col-2 { flex: 0 0 16.666%; max-width: 16.666%; }
14.col-3 { flex: 0 0 25%; max-width: 25%; }
15.col-4 { flex: 0 0 33.333%; max-width: 33.333%; }
16.col-5 { flex: 0 0 41.666%; max-width: 41.666%; }
17.col-6 { flex: 0 0 50%; max-width: 50%; }
18.col-7 { flex: 0 0 58.333%; max-width: 58.333%; }
19.col-8 { flex: 0 0 66.666%; max-width: 66.666%; }
20.col-9 { flex: 0 0 75%; max-width: 75%; }
21.col-10 { flex: 0 0 83.333%; max-width: 83.333%; }
22.col-11 { flex: 0 0 91.666%; max-width: 91.666%; }
23.col-12 { flex: 0 0 100%; max-width: 100%; }
24
25@media (max-width: 768px) {
26  .col-md-12 { flex: 0 0 100%; max-width: 100%; }
27  .col-md-6 { flex: 0 0 50%; max-width: 50%; }
28  .col-md-4 { flex: 0 0 33.333%; max-width: 33.333%; }
29}
30
31@media (max-width: 576px) {
32  .col-sm-12 { flex: 0 0 100%; max-width: 100%; }
33  .col-sm-6 { flex: 0 0 50%; max-width: 50%; }
34}

Wykorzystanie w komponencie:

1// app/page.tsx
2export default function Home() {
3  return (
4    <div className="container">
5      <div className="row">
6        <div className="col col-4 col-md-6 col-sm-12">
7          <div className="card">Kolumna 1</div>
8        </div>
9        <div className="col col-4 col-md-6 col-sm-12">
10          <div className="card">Kolumna 2</div>
11        </div>
12        <div className="col col-4 col-md-12 col-sm-12">
13          <div className="card">Kolumna 3</div>
14        </div>
15      </div>
16    </div>
17  );
18}

Przykład 2: Stylowanie formularzy

1/* Form.module.css */
2.form {
3  margin-bottom: 2rem;
4}
5
6.formGroup {
7  margin-bottom: 1rem;
8}
9
10.label {
11  display: block;
12  margin-bottom: 0.5rem;
13  font-weight: 500;
14}
15
16.input {
17  display: block;
18  width: 100%;
19  padding: 0.75rem;
20  font-size: 1rem;
21  border: 1px solid #ddd;
22  border-radius: var(--border-radius);
23  background-color: white;
24}
25
26.input:focus {
27  outline: none;
28  border-color: var(--primary-color);
29  box-shadow: 0 0 0 3px rgba(58, 134, 255, 0.2);
30}
31
32.error {
33  color: var(--accent-color);
34  font-size: 0.875rem;
35  margin-top: 0.25rem;
36}
37
38.submitButton {
39  composes: button from './Button.module.css';
40  composes: primary from './Button.module.css';
41}

Najlepsze praktyki

  1. Utrzymuj spójną strukturę

    • Globalne style w
      app/globals.css
    • Moduły CSS obok komponentów
    • Konsekwentne nazewnictwo plików (np.
      ComponentName.module.css
      )
  2. Używaj zmiennych CSS dla wartości powtarzających się

    • Kolory
    • Odstępy
    • Rozmiary czcionek
    • Zaokrąglenia
    • Cienie
  3. Twórz klasy użytkowe dla często używanych stylów

    • .text-center
      ,
      .mb-2
      , itp.
  4. Używaj komentarzy dla lepszej organizacji

    1/* 
    2 * TYPOGRAPHY
    3 * -------------
    4 */
    5
    6/* 
    7 * LAYOUT
    8 * -------------
    9 */
  5. Stosuj metodologie CSS (jeśli potrzebne)

    • BEM (Block Element Modifier)
    • SMACSS (Scalable and Modular Architecture for CSS)
    • OOCSS (Object-Oriented CSS)
  6. Preferuj kompozycję nad dziedziczeniem

    • Łącz małe, jednocelowe klasy zamiast tworzyć duże, złożone selektory

Wydajność a stylowanie

Next.js 15 automatycznie optymalizuje CSS:

  1. Podczas produkcyjnej kompilacji CSS jest minimalizowany
  2. CSS Modules są przetwarzane i generowane są unikalne nazwy klas
  3. Style krytyczne są automatycznie wstrzykiwane do znacznika
    <head>

W przypadku większych aplikacji, warto rozważyć:

  1. Code splitting CSS
    • CSS jest dzielony na mniejsze pliki i ładowany tylko wtedy, gdy jest potrzebny
    • W Next.js dzieje się to automatycznie dla CSS Modules
  2. Używanie narzędzi do eliminacji nieużywanego CSS
    • PurgeCSS
    • Unused CSS (ucss)

Rozbudowane przykłady i zastosowania

System komponentów z wykorzystaniem CSS Modules

Poniżej przedstawiamy przykład rozwiniętego systemu komponentów wykorzystujących CSS Modules w aplikacji Next.js 15:

  1. Struktura katalogów:
1components/
2├── ui/
3│   ├── Button/
4│   │   ├── Button.tsx
5│   │   └── Button.module.css
6│   ├── Card/
7│   │   ├── Card.tsx
8│   │   └── Card.module.css
9│   ├── Input/
10│   │   ├── Input.tsx
11│   │   └── Input.module.css
12│   └──
13├── layout/
14│   ├── Header/
15│   │   ├── Header.tsx
16│   │   └── Header.module.css
17│   ├── Footer/
18│   │   ├── Footer.tsx
19│   │   └── Footer.module.css
20│   └──
21└──
  1. Komponent Button z różnymi wariantami:
1// components/ui/Button/Button.tsx
2import styles from './Button.module.css';
3import { ReactNode } from 'react';
4
5type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'outline' | 'text';
6type ButtonSize = 'sm' | 'md' | 'lg';
7
8interface ButtonProps {
9  variant?: ButtonVariant;
10  size?: ButtonSize;
11  children: ReactNode;
12  onClick?: () => void;
13  disabled?: boolean;
14  fullWidth?: boolean;
15  icon?: ReactNode;
16  iconPosition?: 'left' | 'right';
17  className?: string;
18}
19
20export function Button({
21  variant = 'primary',
22  size = 'md',
23  children,
24  onClick,
25  disabled = false,
26  fullWidth = false,
27  icon,
28  iconPosition = 'left',
29  className = '',
30}: ButtonProps) {
31  const buttonClasses = [
32    styles.button,
33    styles[variant],
34    styles[size],
35    fullWidth ? styles.fullWidth : '',
36    icon ? styles.hasIcon : '',
37    icon && iconPosition === 'right' ? styles.iconRight : '',
38    disabled ? styles.disabled : '',
39    className
40  ].filter(Boolean).join(' ');
41
42  return (
43    <button 
44      className={buttonClasses}
45      onClick={onClick}
46      disabled={disabled}
47    >
48      {icon && iconPosition === 'left' && (
49        <span className={styles.icon}>{icon}</span>
50      )}
51      <span className={styles.text}>{children}</span>
52      {icon && iconPosition === 'right' && (
53        <span className={styles.icon}>{icon}</span>
54      )}
55    </button>
56  );
57}
1/* components/ui/Button/Button.module.css */
2.button {
3  display: inline-flex;
4  align-items: center;
5  justify-content: center;
6  font-weight: 500;
7  border: none;
8  border-radius: var(--border-radius);
9  cursor: pointer;
10  transition: all 0.2s ease;
11  font-family: inherit;
12}
13
14/* Variants */
15.primary {
16  background-color: var(--primary-color);
17  color: white;
18}
19
20.primary:hover {
21  background-color: var(--primary-dark);
22}
23
24.secondary {
25  background-color: var(--secondary-color);
26  color: white;
27}
28
29.secondary:hover {
30  background-color: var(--secondary-dark);
31}
32
33.tertiary {
34  background-color: var(--tertiary-color);
35  color: white;
36}
37
38.tertiary:hover {
39  background-color: var(--tertiary-dark);
40}
41
42.outline {
43  background-color: transparent;
44  border: 1px solid var(--primary-color);
45  color: var(--primary-color);
46}
47
48.outline:hover {
49  background-color: rgba(58, 134, 255, 0.1);
50}
51
52.text {
53  background-color: transparent;
54  color: var(--primary-color);
55  padding-left: 0;
56  padding-right: 0;
57}
58
59.text:hover {
60  background-color: transparent;
61  color: var(--primary-dark);
62  text-decoration: underline;
63}
64
65/* Sizes */
66.sm {
67  font-size: 0.875rem;
68  padding: 0.5rem 1rem;
69}
70
71.md {
72  font-size: 1rem;
73  padding: 0.75rem 1.5rem;
74}
75
76.lg {
77  font-size: 1.125rem;
78  padding: 1rem 2rem;
79}
80
81/* Modifiers */
82.fullWidth {
83  width: 100%;
84}
85
86.hasIcon {
87  gap: 0.5rem;
88}
89
90.iconRight {
91  flex-direction: row-reverse;
92}
93
94.disabled {
95  opacity: 0.6;
96  cursor: not-allowed;
97}
98
99.disabled:hover {
100  background-color: var(--primary-color);
101}
102
103.outline.disabled:hover {
104  background-color: transparent;
105}
106
107.text.disabled:hover {
108  background-color: transparent;
109  text-decoration: none;
110}
111
112.icon {
113  display: flex;
114  align-items: center;
115  justify-content: center;
116}
117
118.button .text {
119  display: inline-block;
120}
  1. Użycie komponentu Button:
1// app/examples/page.tsx
2import { Button } from '@/components/ui/Button/Button';
3import { FiDownload, FiHeart, FiArrowRight } from 'react-icons/fi';
4
5export default function ButtonExamplesPage() {
6  return (
7    <div className="container">
8      <h1>Przykłady przycisków</h1>
9      
10      <h2>Warianty</h2>
11      <div className="button-group">
12        <Button variant="primary">Primary</Button>
13        <Button variant="secondary">Secondary</Button>
14        <Button variant="tertiary">Tertiary</Button>
15        <Button variant="outline">Outline</Button>
16        <Button variant="text">Text</Button>
17      </div>
18      
19      <h2>Rozmiary</h2>
20      <div className="button-group">
21        <Button size="sm">Small</Button>
22        <Button size="md">Medium</Button>
23        <Button size="lg">Large</Button>
24      </div>
25      
26      <h2>Z ikonami</h2>
27      <div className="button-group">
28        <Button icon={<FiDownload />}>Pobierz</Button>
29        <Button icon={<FiHeart />} variant="outline">Polub</Button>
30        <Button icon={<FiArrowRight />} iconPosition="right">
31          Przejdź dalej
32        </Button>
33      </div>
34      
35      <h2>Pełna szerokość</h2>
36      <Button fullWidth>Przycisk na pełną szerokość</Button>
37      
38      <h2>Wyłączony</h2>
39      <div className="button-group">
40        <Button disabled>Wyłączony przycisk</Button>
41        <Button variant="outline" disabled>Wyłączony outline</Button>
42      </div>
43    </div>
44  );
45}

Podsumowanie

Stylowanie w Next.js 15 jest elastyczne i umożliwia stosowanie różnych podejść, od globalnych stylów po hermetyczne CSS Modules. Podobnie jak w Metropolis Quantum, gdzie estetyka całego miasta jest spójna, ale każda dzielnica zachowuje swoją unikalność, w aplikacjach Next.js możemy łączyć globalne reguły z lokalnymi stylami komponentów.

Najważniejsze punkty:

  1. Globalne style są idealne do definiowania ogólnych reguł, zmiennych i klas użytkowych
  2. CSS Modules zapewniają lokalne stylowanie bez konfliktów, idealne dla komponentów
  3. Next.js 15 wspiera również Sass, Styled JSX i biblioteki CSS-in-JS
  4. Dobre praktyki organizacji stylów zwiększają czytelność i ułatwiają utrzymanie kodu

W następnym rozdziale przyjrzymy się integracji z Tailwind CSS, popularnym frameworkiem CSS opartym na klasach użytkowych, który może znacząco przyspieszyć proces stylowania w Next.js 15.

Vai a CodeWorlds