Styled Components в React: полное руководство
Стилизация компонентов — одна из ключевых задач при разработке интерфейсов на React. В этом уроке разберём библиотеку (откроется в новой вкладке)styled-components — один из самых популярных инструментов для CSS-in-JS, который позволяет писать стили прямо внутри JavaScript- или TypeScript-файлов рядом с компонентами. Вы узнаете, как создавать стилизованные компоненты, управлять их внешним видом через пропсы и настраивать единую тему оформления для всего приложения.
Что такое styled-components и зачем они нужны
Такой подход решает сразу несколько проблем, знакомых каждому фронтенд-разработчику.
Во-первых, исчезает риск случайного совпадения имён классов — библиотека автоматически генерирует уникальные имена.
Во-вторых, стили компонента живут рядом с самим компонентом, а не в отдельном CSS-файле, что упрощает навигацию по проекту.
В-третьих, неиспользуемый CSS автоматически удаляется: если компонент не рендерится, его стили не попадают в итоговый бандл.
Другие преимущества
- Динамическая стилизация на основе пропсов
- Поддержка тем оформления через
ThemeProvider - Автоматическая расстановка вендорных префиксов
- Возможность наследовать и комбинировать стили компонентов
Дальше на практике посмотрим, как всё это работает.
Установка и первый стилизованный компонент
Для начала работы установите библиотеку через пакетный менеджер:
npm install styled-components
# или
yarn add styled-components
Если вы используете styled-components версии ниже 6, дополнительно понадобится пакет @types/styled-components для корректной работы с TypeScript. Начиная с версии 6 типы уже встроены в саму библиотеку.
Создать стилизованный компонент можно с помощью функции styled, вызывая метод, соответствующий нужному HTML-тегу, — например, styled.button или styled.div. Внутри тегированной шаблонной строки пишется обычный CSS, включая вложенные селекторы и псевдоклассы:
import styled from 'styled-components';
const Button = styled.button`
padding: 12px 24px;
border: none;
border-radius: 8px;
background-color: #326ec1;
color: white;
font-size: 16px;
cursor: pointer;
&:hover {
background-color: #274f8f;
}
`;
function App() {
return <Button>Нажми меня</Button>;
}
Компонент Button из примера выше — это полноценный React-компонент. Он принимает те же пропсы, что и обычный button, и рендерит его в DOM с автоматически сгенерированным классом.
Динамические стили через пропсы
Одно из главных преимуществ styled-components — возможность менять стили в зависимости от пропсов компонента. Внутри шаблонной строки можно использовать функции, которые получают пропсы и возвращают нужное значение:
interface ButtonProps {
variant?: 'primary' | 'secondary';
}
const StyledButton = styled.button<ButtonProps>`
padding: 12px 24px;
border: none;
border-radius: 8px;
color: white;
background-color: ${({ variant }) =>
variant === 'secondary' ? '#6c757d' : '#326ec1'};
`;
function App() {
return (
<>
<StyledButton variant="primary">Основная</StyledButton>
<StyledButton variant="secondary">Вторичная</StyledButton>
</>
);
}
В этом примере значение свойства background-color вычисляется на основе пропса variant. Такой подход избавляет от необходимости писать дополнительные CSS-классы для каждого состояния компонента.
Не создавайте styled-компоненты внутри тела функционального компонента или прямо в JSX на каждый рендер — определяйте их на уровне модуля, вне компонента. В противном случае React будет создавать новый компонент и новый CSS-класс при каждом рендере, что негативно скажется на производительности и приведёт к накоплению лишних стилей в DOM.
Наследование и композиция стилей
styled-components поддерживают наследование стилей: можно взять уже существующий стилизованный компонент и дополнить его новыми правилами с помощью styled(Component):
const Button = styled.button`
padding: 12px 24px;
border-radius: 8px;
border: none;
`;
const DangerButton = styled(Button)`
background-color: #dc3545;
color: white;
`;
function App() {
return <DangerButton as="a" href="/delete">Удалить</DangerButton>;
}
Обратите внимание на проп as — он позволяет отрендерить стилизованный компонент с другим HTML-тегом, сохранив при этом все стили. В примере выше DangerButton рендерится как ссылка a, а не как button, но выглядит так же.
Ещё один полезный инструмент — метод .attrs(), который позволяет задавать HTML-атрибуты компонента по умолчанию, например type="submit" для кнопки формы или placeholder для поля ввода, не засоряя JSX лишними пропсами.
Темизация с ThemeProvider
Когда в проекте нужно поддерживать несколько цветовых схем или просто держать все значения дизайна (цвета, отступы, шрифты) в одном месте, на помощь приходит ThemeProvider. Он оборачивает часть дерева компонентов и передаёт объект темы через React Context — любой styled-компонент внутри получает доступ к теме через специальный проп theme:
import { ThemeProvider } from 'styled-components';
const theme = {
colors: {
primary: '#326ec1',
accent: '#ffb131',
},
};
const Title = styled.h1`
color: ${({ theme }) => theme.colors.primary};
`;
function App() {
return (
<ThemeProvider theme={theme}>
<Title>Заголовок страницы</Title>
</ThemeProvider>
);
}
Внутри шаблонной строки любого styled-компонента доступен параметр theme, из которого можно брать значения — цвета, размеры шрифтов, отступы. Это особенно удобно для реализации переключения между светлой и тёмной темой: достаточно поменять объект, переданный в ThemeProvider, и все компоненты автоматически обновят стили.
Глобальные стили с createGlobalStyle
Помимо стилей отдельных компонентов, часто нужны глобальные правила — сброс отступов у body, подключение шрифта, базовые настройки box-sizing. Для этого styled-components предоставляет функцию createGlobalStyle:
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
font-family: sans-serif;
}
`;
function App() {
return (
<>
<GlobalStyle />
<Title>Приложение</Title>
</>
);
}
Компонент, созданный с помощью createGlobalStyle, не оборачивает разметку и не принимает children — его достаточно один раз отрендерить в корне приложения, и описанные в нём стили применятся ко всему документу.
Итоги
В этом уроке мы разобрались, что такое styled-components и какую проблему решает подход CSS-in-JS. Вы научились создавать стилизованные компоненты, менять их внешний вид с помощью пропсов, наследовать и комбинировать стили через styled(Component) и проп as, а также настраивать единую тему оформления с помощью ThemeProvider и задавать глобальные стили через createGlobalStyle.
В следующем уроке познакомимся с Emotion — ещё одной популярной библиотекой для CSS-in-JS, сравним её со styled-components и разберём, чем отличаются их подходы к API и производительности.