CSS-in-JS: популярные библиотеки (styled-components, emotion) и принцип работы

Что такое CSS-in-JS и зачем он нужен?

CSS-in-JS — это подход, при котором стили пишутся не в отдельных файлах .css, а прямо в JavaScript-коде с помощью специальных библиотек. Это решает несколько проблем традиционного CSS:

  • Изоляция стилей (нет конфликтов классов)
  • Динамическое изменение стилей на лету (проще, чем className-танцы)
  • Поддержка темизации «из коробки»
  • Более тесная интеграция с React/другими фреймворками

🔥 Важно: CSS-in-JS не заменяет обычный CSS, а дополняет его там, где нужна динамика и компонентный подход.

Как это работает под капотом?

Когда вы пишете стили в JS, библиотека делает следующее:

  1. Создаёт уникальные имена классов (например, .jsx-123abc).
  2. Динамически добавляет стили в <head> документа.
  3. Автоматически удаляет неиспользуемые стили при размонтировании компонента.
// Пример: 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 — это мощная альтернатива с двумя режимами работы:

  1. Синтаксис как у styled-components (почти один в один)
  2. 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-стили быстрее)

Теперь вы готовы покорять компонентные стили как настоящий профи! 🎨🚀

Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty