CSS-in-JS: популярные библиотеки (styled-components, emotion) и принцип работы
Что такое CSS-in-JS и зачем он нужен?
CSS-in-JS — это подход, при котором стили пишутся не в отдельных файлах .css, а прямо в JavaScript-коде с помощью специальных библиотек. Это решает несколько проблем традиционного CSS:
- Изоляция стилей (нет конфликтов классов)
- Динамическое изменение стилей на лету (проще, чем
className-танцы) - Поддержка темизации «из коробки»
- Более тесная интеграция с React/другими фреймворками
🔥 Важно: CSS-in-JS не заменяет обычный CSS, а дополняет его там, где нужна динамика и компонентный подход.
Как это работает под капотом?
Когда вы пишете стили в JS, библиотека делает следующее:
- Создаёт уникальные имена классов (например,
.jsx-123abc). - Динамически добавляет стили в
<head>документа. - Автоматически удаляет неиспользуемые стили при размонтировании компонента.
// Пример: styled-components генерирует такой CSS:
.Button-jsx123 {
background: blue;
color: white;
}
Библиотека №1: styled-components
Styled-components — самая популярная библиотека CSS-in-JS. Позволяет создавать стилизованные компоненты через шаблонные строки.
Базовый пример:
import styled from 'styled-components';
const Button = styled.button`
background: ${props => props.primary ? 'blue' : 'gray'};
color: white;
padding: 10px 20px;
border-radius: 5px;
`;
// Использование:
<Button primary>Нажми меня</Button>
Фишки styled-components:
- Пропсы в стилях (как в примере выше)
- Темизация через
<ThemeProvider> - Анимации с
keyframes - Стилизация любых компонентов (даже сторонних)
// Анимация:
const rotate = keyframes`
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
`;
const Spinner = styled.div`
animation: ${rotate} 2s linear infinite;
`;
Библиотека №2: Emotion
Emotion — это мощная альтернатива с двумя режимами работы:
- Синтаксис как у styled-components (почти один в один)
- CSS-пропсы (стили через объекты)
Пример с CSS-пропсами:
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
const style = css({
backgroundColor: 'hotpink',
'&:hover': {
color: 'white'
}
});
<div css={style}>Розовый блок</div>
💡 Обратите внимание на директиву
@jsxImportSource— она нужна для работы синтаксиса.
Плюсы Emotion:
- Меньше размер бандла (иногда критично)
- SSR из коробки (у styled-components нужно настраивать)
- Более гибкий API (можно миксовать оба синтаксиса)
Когда выбрать styled-components, а когда Emotion?
| Критерий | styled-components | Emotion |
|---|---|---|
| Простота | ✅ Лучше для новичков | Требует настройки Babel |
| Размер бандла | 12.5KB | 7.5KB |
| SSR | Нужен plugin | Встроен |
| Синтаксис | Только шаблоны | Шаблоны + объекты |
Выбирайте styled-components, если:
- Нужен максимально простой старт
- Работаете в небольшом проекте
Выбирайте Emotion, если:
- Критичен размер бандла
- Нужен более гибкий синтаксис
- Планируется SSR
Продвинутые практики
1. Динамические стили на основе пропсов
const Box = styled.div`
width: ${props => props.size}px;
background: ${props => {
if (props.error) return 'red';
if (props.success) return 'green';
return 'gray';
}};
`;
2. Глобальные стили
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
font-family: sans-serif;
}
`;
// В корневом компоненте:
<>
<GlobalStyle />
<App />
</>
3. Переиспользование стилей
const baseStyles = css`
padding: 12px;
border-radius: 4px;
`;
const PrimaryButton = styled.button`
${baseStyles}
background: blue;
`;
Главное — не переусердствуйте!
CSS-in-JS — мощный инструмент, но:
- Не используйте его для статичных стилей (лучше обычный CSS)
- Избегайте глубокой вложенности (помните про специфичность)
- Тестируйте производительность (иногда inline-стили быстрее)
Теперь вы готовы покорять компонентные стили как настоящий профи! 🎨🚀