Introdução
Styled-components permite escrever CSS real dentro dos seus arquivos JavaScript, com escopo restrito a um componente específico. Os estilos viajam junto com o componente, eliminando colisões de nomes de classe e acabando com a necessidade de procurar um arquivo CSS separado quando algo parece errado. Se você já perdeu tempo depurando qual folha de estilos global está sobrescrevendo qual, a proposta é imediatamente atraente.
Por que Usar Styled-Components?
Escopo de Estilo
Os estilos são automaticamente limitados ao componente ao qual pertencem. Sem convenções de nomenclatura BEM, sem preocupações com a ordem de cascata entre arquivos.
Estilização Dinâmica
Você pode ramificar com base em props diretamente dentro do template literal. Alternar uma variante não exige mais manter classes CSS paralelas e lógica JavaScript separadas.
Manutenibilidade Aprimorada
Estilos e marcação vivem no mesmo arquivo. Quando um componente é deletado, seus estilos vão junto. Você não descobre CSS órfão um ano depois.
Prefixação de Vendor Automática
Styled-components aplica os prefixes de vendor automaticamente, então você escreve propriedades CSS padrão e ele cuida da compatibilidade entre navegadores.
Primeiros Passos com Styled-Components
Instalação
npm install styled-components
ou
yarn add styled-components
Uso Básico
Veja como criar um componente de botão estilizado:
import React from 'react';
import styled from 'styled-components';
const Button = styled.button`
background-color: #6200ee;
color: white;
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: #3700b3;
}
`;
const App = () => (
<Button>Click Me</Button>
);
export default App;
styled.button retorna um componente React com o CSS aplicado. Você o usa como qualquer outro componente.
Estilização com Props
Styled-components permitem passar props para os elementos estilizados a fim de aplicar estilos condicionalmente.
const Button = styled.button`
background-color: ${props => props.primary ? '#6200ee' : '#white'};
color: ${props => props.primary ? 'white' : '#6200ee'};
padding: 10px 15px;
border: ${props => props.primary ? 'none' : '2px solid #6200ee'};
border-radius: 5px;
cursor: pointer;
&:hover {
background-color: ${props => props.primary ? '#3700b3' : '#f2e7fe'};
}
`;
const App = () => (
<>
<Button primary>Primary Button</Button>
<Button>Secondary Button</Button>
</>
);
export default App;
Ao passar a prop primary, podemos alternar os estilos do botão de forma dinâmica.
Estendendo Styled Components
Você pode criar novos styled components estendendo os existentes:
const OutlineButton = styled(Button)`
background-color: transparent;
color: #6200ee;
border: 2px solid #6200ee;
&:hover {
background-color: #f2e7fe;
}
`;
OutlineButton herda tudo de Button e adiciona suas próprias sobreposições.
Temas com Styled-Components
Para design tokens consistentes em uma árvore de componentes grande, use ThemeProvider.
import { ThemeProvider } from 'styled-components';
const theme = {
primary: '#6200ee',
secondary: '#03dac6',
};
const Button = styled.button`
background-color: ${props => props.theme.primary};
color: white;
padding: 10px 15px;
`;
const App = () => (
<ThemeProvider theme={theme}>
<Button>Themed Button</Button>
</ThemeProvider>
);
Atualize o objeto de tema em um único lugar e todos os componentes que usam props.theme capturam a mudança.
Criando uma Aplicação de Exemplo Completa
Aqui está um app básico de tarefas que demonstra como essas peças se encaixam.
Configurando o Projeto
npx create-react-app styled-components-todo
cd styled-components-todo
npm install styled-components
Estruturando o App
Três componentes:
App: o componente principal e contêiner de estado.TodoList: renderiza a lista de tarefas.TodoForm: formulário para adicionar novas tarefas.
Componente App
// src/App.js
import React, { useState } from 'react';
import styled from 'styled-components';
import TodoForm from './TodoForm';
import TodoList from './TodoList';
const Container = styled.div`
max-width: 500px;
margin: 50px auto;
padding: 20px;
background-color: #f2e7fe;
border-radius: 10px;
`;
const Title = styled.h1`
text-align: center;
color: #6200ee;
`;
const App = () => {
const [todos, setTodos] = useState([]);
const addTodo = text => {
const newTodos = [...todos, { text }];
setTodos(newTodos);
};
return (
<Container>
<Title>Styled Components To-Do App</Title>
<TodoForm addTodo={addTodo} />
<TodoList todos={todos} />
</Container>
);
};
export default App;
Componente TodoForm
// src/TodoForm.js
import React, { useState } from 'react';
import styled from 'styled-components';
const Form = styled.form`
display: flex;
margin-bottom: 20px;
`;
const Input = styled.input`
flex: 1;
padding: 10px;
border: 2px solid #6200ee;
border-radius: 5px;
margin-right: 10px;
font-size: 16px;
`;
const Button = styled.button`
background-color: #6200ee;
color: white;
padding: 0 20px;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
&:hover {
background-color: #3700b3;
}
`;
const TodoForm = ({ addTodo }) => {
const [value, setValue] = useState('');
const handleSubmit = event => {
event.preventDefault();
if (!value) return;
addTodo(value);
setValue('');
};
return (
<Form onSubmit={handleSubmit}>
<Input
type="text"
placeholder="Add a new task"
value={value}
onChange={e => setValue(e.target.value)}
/>
<Button type="submit">Add</Button>
</Form>
);
};
export default TodoForm;
Componente TodoList
// src/TodoList.js
import React from 'react';
import styled from 'styled-components';
const List = styled.ul`
list-style: none;
padding-left: 0;
`;
const ListItem = styled.li`
background-color: white;
padding: 15px 20px;
border-bottom: 1px solid #ddd;
&:nth-child(even) {
background-color: #fafafa;
}
`;
const TodoList = ({ todos }) => (
<List>
{todos.map((todo, index) => (
<ListItem key={index}>{todo.text}</ListItem>
))}
</List>
);
export default TodoList;
Executando a Aplicação
npm start
Navegue até http://localhost:3000 para interagir com seu app de tarefas estilizado.
Conclusão
Styled-components é uma escolha prática quando você quer que estilos e componentes permaneçam sincronizados. CSS com escopo significa sem sobrescritas inesperadas, estilização baseada em props substitui a lógica de classes condicionais, e temas mantêm os design tokens consistentes sem variáveis CSS espalhadas por vários arquivos.
A contrapartida é o tamanho do bundle e o custo de runtime adicional para gerar nomes de classe. Para a maioria das aplicações React essa troca vale a pena, mas é válido fazer benchmarks se você estiver trabalhando em um contexto sensível à performance.
Dicas Adicionais
- Use
createGlobalStylepara resets de base e importações de fontes que devem se aplicar ao documento inteiro. - Ao adicionar styled-components a um projeto existente, migre um componente por vez em vez de fazer uma reescrita completa.
- O plugin Babel do styled-components melhora a legibilidade dos nomes de classe no DevTools e vale a pena adicionar a qualquer projeto não trivial.