styled-components: синтаксис Tagged Template Literals.Створивши структуру React-додатка за допомогою компонентів, ми стикаємося з наступним викликом: як усе це красиво оформити?
Історично склалося так, що CSS був розроблений для документів, де стилі застосовуються глобально (до всіх тегів p, до всіх класів .button). Але в компонентній архітектурі React ми хочемо, щоб стилі кнопки <SidebarButton> впливали тільки на неї і не зламали випадково кнопку <SubmitButton> у формі коментарів через конфлікт імен блоків чи їх вкладеності.
Спроби вирішити цю проблему (ізоляцію) призвели до появи кількох абсолютно різних підходів до стилізації у React екосистемі: від суворої ізоляції CSS Modules до радикального CSS-in-JS та атомарного Tailwind CSS.
Мета цієї лекції — розібрати сучасні стандарти стилізації React-додатків, спробувати написати компоненти за допомогою styled-components та відчути швидкість верстки з Tailwind CSS.
Проблема глобального CSS:
У класичній веб-розробці всі стилі лежать в одному величезному style.css (або скомпільованому з SASS). Коли проект росте, виникають конфлікти імен:
A створив клас .card для відгуків.B (на іншій сторінці) теж створив клас .card для списку товарів.Щоб цього уникнути, придумали жорсткі правила іменування — БЕМ (BEM): .card__title--active. Але писати і підтримувати такі довгі класи важко.
Тому індустрія почала шукати способи інкапсулювати (ізолювати) CSS на рівні окремих React-компонентів.
До того як перейти до сучасних лідерів, згадаємо три вбудовані способи стилізації:
1. Глобальні таблиці стилів (Звичайний CSS)
Просто імпортуємо файл import './App.css'; у компонент.
Мінус: Стилі все одно стають глобальними для всієї сторінки. Конфлікти неминучі.
2. Inline-стилі (Вбудовані)
Стилі передаються безпосередньо в атрибут style як JS-об’єкт.
// Зверніть увагу: camelCase і об'єкт замість рядка
<button style=>Клікни</button>
Мінус: Неможливо використовувати Media Queries (@media), псевдокласи (:hover, :active) та ключові (keyframes) анімації.
3. CSS Modules
Це вбудований у Vite/CRA механізм. Ви створюєте файл з назвою Button.module.css. При його імпорті всі імена класів автоматично перетворюються на унікальні хеші (наприклад, .btn_xz89a), тому конфлікти виключені.
import styles from "./Button.module.css";
// ...
<button className={styles.submitBtn}>Відправити</button>;
Мінус: Це все ще окремі CSS-файли, що не мають прямого доступу до JS-змінних компонента (State/Props).
Що, якби ми взагалі перестали писати окремі файли .css?
CSS-in-JS — це парадигма, де CSS-код пишеться з використанням JavaScript безпосередньо у файлі компонента.
Найпопулярніша бібліотека, що реалізує цей підхід — styled-components.
Головна її ідея полягає в тому, що замість написання CSS-класів і подальшого призначення їх HTML-тегам, ми створюємо нові готові React-компоненти, у які вже намертво вшиті потрібні нам стилі.
styled-componentsВстановлення бібліотеки:
npm install styled-components
Синтаксис ґрунтується на унікальній фішці JavaScript ES6 — Tagged Template Literals (тег-шаблони рядків з використанням зворотних апострофів `).
import styled from "styled-components";
// 1. Створюємо стилізований компонент (завжди з великої літери!)
// styled.button означає, що під капотом це буде звичайний HTML-тег <button>
const StyledButton = styled.button`
background-color: blue;
color: white;
padding: 10px 20px;
border-radius: 5px;
border: none;
cursor: pointer;
/* Ми можемо використовувати звичайний CSS синтаксис, навіть псевдокласи! */
&:hover {
background-color: darkblue;
}
`;
function App() {
return (
<div>
{/* 2. Просто використовуємо його як звичайний React компонент */}
<StyledButton>Натисни мене</StyledButton>
</div>
);
}
Під капотом бібліотека сама згенерує випадковий, унікальний клас (наприклад, .sc-aVfwe) і вставить його у <head> сторінки. Конфлікти виключені на 100%.
Наймогутніша фішка styled-components — це здатність динамічно змінювати CSS на основі Пропсів (Props) вашого React компонента.
Оскільки наші стилі написані всередині JS-шаблону (в апострофах ` `), ми можемо вставляти туди JS-функції за допомогою конструкції ${...}. Ця функція першим аргументом отримає всі пропси компонента.
import styled from "styled-components";
// Якщо пропс primary = true, колір буде синім, інакше - сірим
const ActionButton = styled.button`
padding: 10px 20px;
border-radius: 4px;
color: white;
/* Динамічний блок: */
background-color: ${(props) => (props.primary ? "blue" : "gray")};
/* Ще один приклад складнішої логіки (розмір) */
font-size: ${(props) => (props.size === "large" ? "24px" : "16px")};
`;
function Panel() {
return (
<div>
{/* Ця кнопка буде великою і синьою */}
<ActionButton primary size="large">
Зберегти
</ActionButton>
{/* Ця кнопка буде маленькою і сірою */}
<ActionButton>Скасувати</ActionButton>
</div>
);
}
Це означає, що вам більше не потрібно вручну перемикати 10 різних класів типу btn-primary, btn-large за допомогою конкатенації рядків. Ви керуєте дизайном через дані (State/Props).
Незважаючи на потужність styled-components, останні кілька років світ Frontend захопила зовсім інша філософія — Tailwind CSS.
Tailwind — це так званий Utility-first фреймворк.
Замість того, щоб писати класи з назвами сутностей (як .card, .button) і набивати їх десятками властивостей, Tailwind пропонує тисячі заздалегідь написаних мікрокласів (utilities). Кожен мікроклас робить рівно ОДНУ річ.
Наприклад:
flex означає display: flex;p-4 означає padding: 1rem;text-center означає text-align: center;bg-red-500 означає червоний фон певного відтінку.Ми просто накидаємо ці класи прямо в HTML (JSX) як Лего:
// Кнопка з допомогою Tailwind:
<button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Натисни мене
</button>
Переваги Tailwind:
.wrapper, .container, .inner-box).App.jsx та App.css), весь дизайн відбувається на місці.p- (padding), m- (margin).pt- (top), pr- (right), px- (ліво+право), py- (верх+низ).p-4 = 16px відступу з усіх боків.text-sm, text-lg, text-xl (розмір шрифта).font-bold, font-semibold (товщина).bg-red-500 (фон червоний середньої насиченості), text-white (білий текст).flex, flex-col (у стовпець), justify-center, items-center (центрування).grid, grid-cols-3 (сітка на 3 колонки).hover:bg-red-600 (фон зміниться тільки при наведенні мишки).focus:border-blue-500 (зміна рамки при кліку в поле вводу).md: (планшет) або lg: (десктоп) змінюють дизайн на великих екранах.<div className="w-full md:w-1/2">...</div> (На мобілці ширина 100%, на екранах більше 768px — 50%).Немає єдиного “правильного” шляху стилізації в React. Вибір залежить від команди та проекту:
| Інструмент | Плюси | Мінуси | Коли використовувати |
|---|---|---|---|
| CSS Modules | Нульовий поріг входу (звичайний CSS), не потрібні нові бібліотеки. Гарантія ізоляції. | Немає прямого доступу до Props. Складно будувати загальні дизайн-системи. | Для маленьких проектів, або якщо команда тільки переходить зі звичайного HTML/CSS. |
| Styled Components (CSS-in-JS) | Потужна динаміка (пропси керують CSS). Компоненти мають семантичні імена (<Container>, <Header>). |
Уповільнює рендеринг складної сторінки (CSS генерується “на льоту” через JS). | Для створення UI-кітів (Бібліотек компонентів), де кожен елемент є інкапсульованою логічною одиницею з десятками станів. |
| Tailwind CSS | Нереальна швидкість верстки. Єдина система відступів/кольорів. Нульовий розмір фінального CSS-файлу. | JSX перетворюється на нечитабельне “болото” довгих класів (захаращення розмітки). Потрібно вчити багато нових абревіатур. | Для швидких стартапів, прототипів (MVP) та великих проектів, де потрібно багато кастомного і швидкого UI. Це індустріальний стандарт №1 сьогодні. |
styled-components) пропонує створювати стилізовані HTML-теги як готові React-компоненти за допомогою Tagged Template Literals. Це дозволяє прокидати Props зі State прямо всередину CSS.style.css у великих веб-додатках (до епохи ізоляції)? Що таке “Специфічність CSS”?.card і .btn у термінах мікро-класів (просторо/колір)?m-4, p-2, bg-blue-600, hover:text-red-300, flex?