Esse exemplo está na documentação 😄
npm install styled-components
-- ou --
yarn add styled-components
⚠️ Observação: é altamente recomendado, mas não obrigatório, utilizar o plugin do Babel. Algumas vantagens são nomes de classes mais legíveis, SSR, bundle menor, e outros.
styled-components usa tagged template literals para estilizar os componentes. Essa abordagem elimina completamente o mapeamento entre estilo e componente. Ou seja, quando você define um estilo, você está criando um componente normal do React.
O exemplo abaixo cria dois componentes e usa eles.
// Cria um componente Title, um h1 com estilos
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// Cria um componente Wrapper, uma section estilizada
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
// Use-os como você usaria qualquer outro componente
render(
<Wrapper>
<Title>Hello World!</Title>
</Wrapper>
);🔥 Detalhe! O css gerado já tem os prefixos de navegadores. Vai em frente, usa todas as propriedades hipsters que você conhece ;)
O styled-components gera um componente, certo?
Se gera um componente, pode ter props.
E se tem props, você pode usar.
Esse exemplo abaixo tem um estado primary que muda as cores com base na presença (ou ausência) da prop. Para isso, basta usar a famosa interpolação ;)
const Button = styled.button`
background: ${(props) => (props.primary ? 'palevioletred' : 'white')};
color: ${(props) => (props.primary ? 'white' : 'palevioletred')};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);Às vezes precisamos fazer pequenas adaptações no layout de um componente.
Com o styled-components, basta envolvê-lo no construtor styled:
// Botão do exemplo acima, sem as interpolações
const Button = styled.button`
color: palevioletred;
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
// Um novo Botão, baseado no anterior, com alguns detalhes a mais
const TomatoButton = styled(Button)`
color: tomato;
border-color: tomato;
`;
render(
<div>
<Button>Normal Button</Button>
<TomatoButton>Tomato Button</TomatoButton>
</div>
);Ainda, é possível substituir o elemento gerado. Por exemplo, se quiséssemos que, ao invés de um button, nosso componente TomatoButton /> gerasse um a, é só fazer:
<Button as='a' href='/'>
Link com estilos de Button
</Button>📚 Leitura recomendada: Talia Marcassa escreveu uma ótima revisão do uso no mundo real, apresentando muitos insights práticos sólidos e comparações com alternativas, em Styled Components: To Use or Not to Use?
O styled-components usa um pré-processador chamado stylis, que suporta a sintaxe do SCSS.
const Thing = styled.div.attrs((/* props */) => ({ tabIndex: 0 }))`
color: blue;
&:hover {
color: red; // <Thing> quando passamos o mouse
}
& ~ & {
background: tomato; // <Thing> como irmão de <Thing>, mas talvez não diretamente adjacente
}
& + & {
background: lime; // <Thing> adjacente a <Thing>
}
&.something {
background: orange; // <Thing> tagueado com uma classe CSS adicional ".something"
}
.something-else & {
border: 1px solid; // <Thing> dentro de outro elemento nomeado ".something-else"
}
`;
render(
<React.Fragment>
<Thing>Hello world!</Thing>
<Thing>How ya doing?</Thing>
<Thing className='something'>The sun is shining...</Thing>
<div>Pretty nice day today.</div>
<Thing>Don't you think?</Thing>
<div className='something-else'>
<Thing>Splendid.</Thing>
</div>
</React.Fragment>
);Para evitar wrappers desnecessários que apenas passam algumas props para o componente ou elemento renderizado, você pode usar o construtor .attrs. Ele permite que você anexe props adicionais (ou "atributos") a um componente.
Dessa forma, você pode, por exemplo, anexar props estáticas a um elemento ou passar uma prop de terceiros como activeClassName para o componente Link do React Router.
Além disso, você também pode anexar props mais dinâmicas a um componente. O objeto .attrs também pode receber funções, que recebem as props que o componente recebe. O valor de retorno será mesclado com os props resultantes também.
Aqui, renderizamos um componente input e anexamos alguns atributos dinâmicos e estáticos a ele:
const Input = styled.input.attrs((props) => ({
// podemos definir props estáticas
type: 'text',
// ou definir props dinâmicas
size: props.size || '1em',
}))`
color: palevioletred;
font-size: 1em;
border: 2px solid palevioletred;
border-radius: 3px;
/* aqui usamos a prop computada dinamicamente */
margin: ${(props) => props.size};
padding: ${(props) => props.size};
`;
render(
<div>
<Input placeholder='Um input pequeno' />
<br />
<Input placeholder='input maior' size='2em' />
</div>
);Por fim, vamos dar aquela animada nos nossos componentes?
Animações CSS definidas com @keyframes são globais, e isso pode levar a colisão de nomes. O styled-components fornece um helper para mitigar esse problema:
// Criar a animação
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
// Criar um componente que vai rotacionar o que receber
const Rotate = styled.div`
display: inline-block;
animation: ${rotate} 2s linear infinite;
padding: 2rem 1rem;
font-size: 1.2rem;
`;
render(
<Rotate> < 💅🏾 > </Rotate>
);
⚠️ Keyframes não é suportada pelo React Native.
- Do Sass e BEM ao CSS-in-JS: A (re)evolução do CSS ao longo da história 🚀 - Felipe Fialho
- What actually is CSS-in-JS? - Oleg Isonen
- The tradeoffs of CSS-in-JS - Oleg Isonen
- CSS-in-JS - Wikipedia
- Why you should definitely learn how to use CSS-in-JS - Brent Jackson
- Utilizando Styled Components (CSS-in-JS) no ReactJS e React Native | Diego Fernandes - RocketSeat
- Styled Components, por onde começar? Os poderes do CSS in JS - Mario Souto
- JSS - JSS
- Basics - Styled Components
Made with 💜