5 motivos para usar Styled Components

5 motivos para usar Styled Components

Styled Components é uma biblioteca feita para React e React Native. Ela utiliza uma mistura de CSS e Javascript usando uma técnica chamada CSS-in-JS.

É também baseada em marcadores template strings do Javascript, isso significa que quando vamos estilizar o nosso componente, o CSS é escrito entre crases. Isso garante aos desenvolvedores a flexibilidade de reutilizar o código de CSS.

Componentes estilizados são componentes React fáceis de serem feitos com a utilização do styled-components, onde posso utilizar CSS puro dentro do meu código Javascript.

Mais adiante veremos alguns exemplos.

Componentes estilizados

O principal ponto que você deve entender sobre o Styled Components é que o seu nome deve ser levado literalmente ao pé da letra! Você não irá mais estilizar elementos HTML ou componentes baseados em suas classes, você irá criar componentes estilizados que possuem o seu próprio estilo encapsulado, e assim você poderá utilizar esse componente livremente em todo o seu código.

Nesse primeiro exemplo mostro como estilizamos um header de maneira convencional, utilizando CSS puro:

const App = () => {
  return (
		<section className="wrapper">
		   <h1 className="title" >
		     Hello World
		   </h1>
		<section>
  );
};


//styles
section.wrapper {
	padding: 4em;
  background: #273A50;
}

h1.title {
	font-size: 1.5em;
  text-align: center;
  font-family: 'Tahoma';
  color: #E82C50;
}

Agora, vamos construir o nosso primeiro componente com styled-components que irá possuir o seu próprio estilo encapsulado:

import styled from 'styled-components'

// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
  padding: 4em;
  background: #273A50;
`;

// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  font-family: 'Tahoma';
  color: #E82C50;
`;

const App = () => {
  return (
    <Wrapper>
      <Title>Hello World!</Title>
    </Wrapper>  );
};

Fácil, certo? Isso parece ser uma pequena diferença, e de fato é, mas o maior impacto é que agora os estilos fazem parte do componente, o que nos traz diversos benefícios, como usar o mesmo componente em qualquer parte de código, e também eliminar as chances de name bugs, como classes ou estilos repetidos, erros ortográficos ou sobreposições.

Agora que já sabemos como construir um componente, quero mostrar para vocês 5 motivos que vão fazer você querer usar styled-components hoje mesmo!

#1. Global Stylesheet

Quando iniciamos um projeto React a maioria das vezes fazemos um reset de estilos iniciais, aqueles que "vem de fábrica", para que todas as definições de estilos que iremos passar durante a construção do código sejam aplicadas sem erro.

Normalmente, os componentes estilizados são automaticamente delimitados para uma classe CSS local e, portanto, isolados de outros componentes. No caso de createGlobalStyle, essa limitação é removida e coisas como redefinições de CSS ou folhas de estilo base podem ser aplicadas.

import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
  *, *::before, *::after {
    box-sizing: border-box;
  }

  a {
    text-decoration: none;
  }
`;


const App = () => {
  return (
    <>
      <GlobalStyle />
      <Button onClick={() => alert('clicked!')} type="button">
        Link
      </Button>
    </>
  );
};

Coloque o componente <GlobalStyle /> no topo da sua árvore React e os estilos globais serão injetados quando o componente for renderizado.

Pronto! Dessa forma todos os estilos que você aplicar dentro do GlobalStyle serão disseminados para toda aplicação.

#2. Adaptação baseada em props

Quando desenvolvemos aplicações usando React um termo muito conhecido é props, que significa propriedades, e são dados passados a um componente para serem usados por ele. Esses dados podem ser números, strings, booleans e até mesmo outro componente React.

No contexto de styled-components eu posso usar as props para definir cores ou qualquer outro estilo do meu componente. Com as funções CSS do styled-components podemos usar props para condicionalmente renderizar determinado estilo.

Isso reduz a desordem em nossos componentes, e também mantém uma separação de preocupações entre CSS e JavaScript.

Veja como aplicar:

const Button = styled.button`
	border: 2px solid black;
  border-radius: 30px;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 5em;

  /* Adapt the colors based on primary prop */
  background: ${(props) => (props.primary ? "#273A50" : "white")};
  color: ${(props) => (props.primary ? "white" : "#273A50")};

  /* Adapt the colors based on color prop */
  ${({ color }) =>
    color
      ? css`
          background: ${color};
          border-color: ${color};
          color: white;
        `
      : null}
`;

const App = () => {
  return (
    <div>
	    <Button>Normal</Button>
	    <Button primary>Primary</Button>
	    <Button color="#E82C50">Red</Button>
	  </div>
  );
};

E esse é o nosso resultado:

#3. Extensão de estilos

Acredito que todo mundo já teve aquele momento em que estamos desenvolvendo uma aplicação, criamos um componente, seguimos com a criação e um pouco mais à frente precisamos do mesmo componente, mesmo tamanho, mesmo altura, mesmo tamanho de fonte, mas com uma pequena diferença: a cor!

O que fazer? Criar outro componente? Praticamente duplicar o código? Não! Com o styled-components conseguimos estender os estilos de um componente para a criação de outro! Com isso ganhamos tempo, e também um código menos verboso.

Para criarmos facilmente um novo componente que herda o estilo de outro, basta envolvê-lo no construtor styled(). Vamos usar o botão do exemplo anterior, estendendo-o com um novo estilo relacionado a cor:

import styled from 'styled-components';

const Button = styled.button`
	border: 2px solid black;
  border-radius: 30px;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 5em;
`;

// A new component based on Button, but with some override styles
const RedButton = styled(Button)`
  color: #E82C50;
  border-color: #E82C50;
`;

const App = () => {
  return (
    <>
      <Button>Normal Button</Button>
      <RedButton>Red Button</RedButton>
    </>
  );
};

Pronto! Dessa forma criamos um novo componente de forma fácil e rápida.

#4. Temas

Hoje em dia a criação de temas para uma aplicação é muito importante. Com eles nós temos em um só lugar todos os estilos de determinado tema, e com isso ganhamos muita facilidade de manutenção e uso.

O styled-components nos dá todo o suporte para criação de temas exportando o wrapper component <ThemeProvider>. Este componente vai fornecer um tema para todos os componentes do React por meio da API de contexto.

Na árvore de renderização do React, todos os componentes com estilo terão acesso ao tema fornecido, mesmo quando estiverem vários níveis abaixo.

Vamos configurar um objeto de tema com o estilo de CSS que queremos aplicar aos nossos componentes estilizados:

import { ThemeProvider } from "styled-components"

const theme = {
    boderColor: "green",
    color: "green",
    bgColor: "green"
}

Agora, vamos criar dois componentes: Button e Div e aplicar o tema neles:

const Button = styled.button`
    padding: 2px 5px;
    color: ${props => props.theme.color};
    border-radius: 3px;
`

const Div = styled.div`
    padding: 10px;
    color: ${props => props.theme.color};
    border: 1px solid ${props => props.theme.borderColor};

Como podemos ver, esses componentes estão acessando a propriedade theme em suas props.

Agora, vamos renderizar os nossos componentes entre o ThemeProvider e passar o objeto theme como como props:

const App = () => {
  return (
    <ThemeProvider theme={theme}>
	    <Div>
        <Button>Click Me</Button>
	    </Div>
		</ThemeProvider>
  );
};

O objeto theme será fornecido aos "filhos" do ThemeProvider . Agora, se alterarmos qualquer valor no objeto de tema, o ThemeProvider passará as alterações para os filhos e Div e Button e assim alterar seu estilo.

#5. Componentes responsivos


Todo desenvolvedor front-end se preocupa com a responsividade de suas aplicações. Há algumas formas de conseguir uma aplicação fluída para todos os tipos de tela, e uma delas é a utilização de @media queries.

No entanto, o código pode ficar verboso pela grande repetição de blocos de códigos para mudar muitas vezes somente uma propriedade de estilo como por exemplo, um padding.

import styled from "styled-components";

export const Wrapper = styled.div`
  padding: 100px;
  @media screen and (max-width: 1200px) {
    padding: 80px;
  }
  @media screen and (max-width: 800px) {
    padding: 60px;
  }
  @media screen and (max-width: 600px) {
    padding: 40px;
  }
  @media screen and (max-width: 450px) {
    padding: 20px;
  }
`;

export const Title = styled.h1`
  font-size: 5rem;
  @media screen and (max-width: 1200px) {
    font-size: 4rem;
  }
  @media screen and (max-width: 800px) {
    font-size: 3rem;
  }
  @media screen and (max-width: 600px) {
    font-size: 2.4rem;
  }
  @media screen and (max-width: 450px) {
    font-size: 1.6rem;
  }
`;

export const Content = styled.section`
  font-size: 3rem;
  margin: 60px 0;
  @media screen and (max-width: 1200px) {
    font-size: 2.4rem;
    margin: 40px 0;
  }
  @media screen and (max-width: 800px) {
    font-size: 1.8rem;
  }
  @media screen and (max-width: 600px) {
    font-size: 1.6rem;
    margin: 20px 0;
  }
  @media screen and (max-width: 450px) {
    font-size: 1.2rem;
  }
`;

Muita coisa, certo? Imagina se tivéssemos que fazer isso repetidas vezes em todo o código!

Agora, para melhorar tudo isso, vamos escrever uma função breakpoints que vai utilizar o que aprendemos sobre compartilhamento de código com styled-components e então gerar essas media queries. Queremos que a função receba argumentos para:

→ A propriedade CSS à qual estamos aplicando os breakpoints de tela
→ As propriedades CSS
→ Os valores dos breakpoints (da tela e da propriedade CSS)
→ O tipo de media query: max-width, min-width, max-height, min-height.

import { css } from "styled-components";

export const breakpoints = (
  cssProp = "padding", // a propriedade CSS para aplicar nos breakpoints
  cssPropUnits = "px", // as unidades das propriedades do CSS 
  values = [], // array de objetos, ex:[{ 800: 60 }, ...] <-- 800 (key) = screen breakpoint, 60 (value) = CSS prop breakpoint
  mediaQueryType = "max-width" // tipo de media query breakpoint ex: max-width, min-width, max-height, min-height
) => {
  const breakpointProps = values.reduce((mediaQueries, value) => {
    const [screenBreakpoint, cssPropBreakpoint] = [
      Object.keys(value)[0],
      Object.values(value)[0],
    ];
    return (mediaQueries += `
    @media screen and (${mediaQueryType}: ${screenBreakpoint}px) {
      ${cssProp}: ${cssPropBreakpoint}${cssPropUnits};
    }
    `);
  }, "");
  return css([breakpointProps]);
};

Agora podemos usar essa função para nos livrar das inúmeras consultas @media e  reformatar nossos componentes estilizados, veja como é fácil a aplicação:

import styled from "styled-components";

import { breakpoints } from "./utils";

export const Wrapper = styled.div`
  padding: 100px;
  ${breakpoints("padding", "px", [
    { 1200: 80 },
    { 800: 60 },
    { 600: 40 },
    { 450: 20 }
  ])};
`;

export const Title = styled.h1`
  font-size: 5rem;
  ${breakpoints("font-size", "rem", [
    { 1200: 4 },
    { 800: 3 },
    { 600: 2.4 },
    { 450: 1.6 }
  ])};
`;

export const Content = styled.section`
  font-size: 3rem;
  margin: 60px 0;
  ${breakpoints("font-size", "rem", [
    { 1200: 2.4 },
    { 800: 1.8 },
    { 600: 1.6 },
    { 450: 1.2 }
  ])};
  ${breakpoints("margin", "", [{ 1200: "40px 0" }, { 600: "20px 0" }])}; // apply units directly to CSS prop values
`;

Veja quantas linhas de código conseguimos diminuir, a velocidade que ganhamos na criação e também na facilidade de manutenção de código.

Conclusão

Quando falamos de escrever componentes sustentáveis e escaláveis, styled-components é o melhor amigo dos desenvolvedores, já que segue as ideias originais por trás da arquitetura React e estilo dinâmico.

Essas foram algumas das diversas ferramentas que o styled-components nos fornece! Caso queira saber mais, acesse a documentação aqui.

Espero que tenham gostado! Testem, usem a criatividade e tirem suas conclusões :)