Модуль 31

Стилізація в React: CSS, CSS Modules, styled-components

Ось готовий урок, згенерований у стилі CS50: енергійний, зрозумілий та орієнтований на розуміння суті.


🎨 CS50: Стилізація в React — Від хаосу до порядку

Привіт, світе! Мене звати (Ваш ШІ-інструктор), і це — React.

Сьогодні ми не просто "фарбуватимемо кнопки". Ми вирішуватимемо одну з найстаріших і найболючіших проблем веброзробки — як зробити так, щоб ваш сайт виглядав гарно і при цьому код не перетворився на смітник.

Ми розберемо три підходи: "Старий добрий" CSS, CSS Modules та styled-components.


1. 🔥 Вступ: Чому CSS — це мінне поле?

Уявіть, що ви живете у величезному гуртожитку на 1000 кімнат. І в цьому гуртожитку є дивне правило: імена унікальні лише глобально.

Якщо ви назвете свого кота "Барсик", то жоден інший кіт у будівлі не може бути "Барсиком", або (що ще гірше) всі коти раптово стануть відгукуватися на це ім'я і поводитися однаково.

У веброзробці це називається Глобальна область видимості (Global Scope).

Уявіть ситуацію: 1. Ви працюєте над компонентом Header і створюєте клас .button { color: blue; }. Все чудово. 2. Ваш колега через тиждень робить компонент DeleteAccount і теж називає клас .button, але дає йому { color: red; }. 3. Бум! Оскільки CSS глобальний, всі кнопки на сайті раптово стають червоними. Або синіми. Залежить від того, чий файл завантажився останнім.

Питання до вас: Як нам писати стилі так, щоб не боятися випадково зламати верстку на іншій сторінці сайту?

Саме це ми сьогодні й з'ясуємо.


2. 🧠 Теоретична база: Що "під капотом"?

Давайте розкладемо все по поличках. У нас є три шляхи еволюції.

1. Звичайний CSS (The Old School)

Ви створюєте файл App.css, імпортуєте його в App.js. * Як це працює: Webpack бере цей файл і просто додає його як тег <style> у head вашого документа. * Проблема: Всі класи глобальні. Конфлікти неминучі. * Вердикт: Можна використовувати для дуже маленьких проєктів, але небезпечно для великих.

2. CSS Modules (Ізоляція)

Це той самий CSS, але з магією збірки. * Як це працює: Ви називаєте файл Button.module.css. Коли ви пишете клас .btn, Webpack під час збірки автоматично перейменовує його на щось унікальне, наприклад: .Button_btn__xh7a1. * Аналогія: Це ніби у кожного в гуртожитку своя замкнена кімната. Ваш "Барсик" живе лише у вашій кімнаті. * Головне запам'ятати: Класи стають властивостями об'єкта.

3. styled-components (CSS-in-JS)

Тут ми ламаємо стереотипи. Ми пишемо CSS прямо всередині JavaScript файлів. * Як це працює: Бібліотека створює унікальний клас "на льоту", вставляє його в head, і прив'язує до конкретного компонента React. * Фішка: Ви можете змінювати стилі динамічно, передаючи props (аргументи). * Аналогія: Це як розумний одяг, який змінює колір залежно від вашого настрою (стану компонента).


3. 🧪 Приклади (Show me the code!)

Давайте подивимось, як це виглядає в реальності. Що ви очікуєте побачити в кожному випадку?

Рівень 1: CSS Modules (Золота середина)

Ми хочемо кнопку, стиль якої ніколи не "витече" назовні.

Файл: Button.module.css

/* Звичайний CSS, нічого нового */
.error {
  background-color: red;
  color: white;
  padding: 10px;
}

Файл: Button.jsx

import styles from './Button.module.css'; // 👈 Зверніть увагу на імпорт об'єкта

export default function Button() {
  // Ми звертаємось до класу як до змінної!
  return <button className={styles.error}>Delete</button>;
}

Що відбувається в браузері? Кнопка отримає клас на кшталт class="Button_error__ax9z3". Конфлікти неможливі.


Рівень 2: styled-components (Динаміка)

А тепер уявіть, що нам потрібна кнопка, яка може бути "первинною" (синьою) або звичайною (сірою) залежно від пропсів. Без if-else у класах.

import styled from 'styled-components';

// 1. Ми створюємо компонент, який ВЖЕ має стилі
// Використовуємо зворотні лапки (template literals)
const StyledButton = styled.button`
  padding: 10px 20px;
  border-radius: 5px;
  border: none;
  cursor: pointer;

  /* 2. Магія: функція всередині CSS */
  background-color: ${props => props.$primary ? "blue" : "gray"};
  color: white;

  &:hover {
    opacity: 0.8;
  }
`;

export default function App() {
  return (
    <div>
      <StyledButton>Звичайна</StyledButton>
      <StyledButton $primary>Головна</StyledButton> {/* 👈 Передаємо проп */}
    </div>
  );
}

Чому це круто? Ми інкапсулювали логіку вигляду всередину самого стилю. React компонент залишається чистим.


4. 🛠 Практична частина

Прийшов час забруднити руки кодом! Виконайте ці завдання:

  1. 🔹 База: Створіть компонент Card і стилізуйте його за допомогою CSS Modules. Додайте тінь, округлення та відступи. Перевірте в інспекторі браузера, яке ім'я отримав клас.
  2. 🔹 Рефакторинг: Візьміть попередній приклад і перепишіть його на styled-components.
  3. 🔹 Динаміка: Додайте до вашої картки (на styled-components) проп isActive. Якщо він true, рамка картки має ставати зеленою.
  4. 🔹 Реальна задача: Зробіть компонент Avatar.
    • Використайте styled-components.
    • Він має приймати проп size ("small", "medium", "large").
    • Змінюйте ширину і висоту картинки відповідно до розміру (наприклад, 40px, 80px, 120px).
  5. 🔹 Міні-кейс ("А що, якщо..."): Спробуйте використати псевдоклас :hover у CSS Modules і в styled-components. У чому різниця в синтаксисі? (Спойлер: у styled-components ми використовуємо &).
  6. 🔹 Debugging: Спробуйте в styled-components написати CSS властивість з помилкою (наприклад colr: red). Що покаже консоль або редактор?

5. 💡 Мислення як у розробника

Ви вже знаєте синтаксис, але як думає Senior Developer?

  1. Не змішуйте підходи. Найгірше, що можна зробити — це в одному компоненті використати Modules, в іншому — styled-components, а в index.html ще й шматок глобального CSS. Оберіть одну стратегію на проєкт і дотримуйтесь її.
  2. Називайте файли зрозуміло. Якщо це модуль, він мусить мати в назві .module.css. React (і Create React App / Vite) покладаються на це розширення файлу, щоб увімкнути ізоляцію. Якщо забудете .module, стилі стануть глобальними!
  3. Логіка відокремлена від стилів?
    • У CSS Modules стилі лежать окремо (це добре для розділення відповідальності).
    • У CSS-in-JS стилі лежать разом з компонентом (це добре для переносності компонента).
    • Запитайте себе: "Чи планую я перевикористовувати цей компонент в іншому проєкті?". Якщо так, CSS-in-JS може бути зручнішим (один файл скопіював — і все працює).

6. 🧩 Підсумок

Отже, що ми сьогодні вивчили?

  • Глобальний CSS — це як кричати в мегафон: чують усі, і це часто заважає.
  • CSS Modules — дають нам унікальні імена автоматично (Scope), дозволяючи писати звичайний CSS безпечно.
  • styled-components — перетворюють стилі на повноцінні компоненти з логікою (пропсами).

Тепер ви вмієте: Створювати красиві React-застосунки, де стилі не "ламаються" при додаванні нового компонента, і можете робити дизайн адаптивним до стану даних.

🚀 Що далі? Тепер, коли наш інтерфейс виглядає чудово, він все ще "дурний" — він показує лише те, що ми вписали в код руками. На наступному уроці ми навчимося оживляти його реальними даними. Готуйтеся до теми: "UseEffect та робота з API: спілкування із зовнішнім світом".

А поки що... це був CS50. Щасти вам з кодом!