DEV Community

Cover image for Parte 01: Alternativas ao Styled Components - SCSS
Vinícius Vieira
Vinícius Vieira

Posted on

4 1

Parte 01: Alternativas ao Styled Components - SCSS

Nas últimas semanas a comunidade de desenvolvedores React não fala em outra coisa além da descontinuação do Styled Components.

Recentemente seu criador, Evan Jacobs, anunciou que uma das bibliotecas de estilização mais usadas em aplicações React-based está entrando em modo de manutenção, conforme podemos ler na íntegra aqui.

No post citado acima, Jacobs cita os motivos por trás desta decisão:

  1. The React core team has decided to defacto-deprecate certain APIs like the Context API (not available in RSC with no migration path.)
  2. The ecosystem in general has largely moved on from css-in-js as a concept while other technologies like tailwind have absolutely exploded in popularity.
  3. quantizor (me, the core maintainer for styled-components since ~2018) no longer has active production deployments of styled-components in larger applications, so context of usage in real products will continue to wane and eventually cease altogether.

Mas não há motivo para pânico! Existem várias opções para o seu projeto deixar de usar o Styled Components aos poucos.

Analisei duas tecnologias muito promissoras: o SCSS e o Tailwind. Na Parte 01 deste artigo vou mostrar como podemos migrar a estilização do Styled Components para o SCSS e contar um pouco dos meus aprendizados utilizando SCSS ao longo do processo.

1. O projeto

Repositório: https://github.com/vini-ak/styled-components-migration

Para exemplificar o processo de migração de Styled Components para SCSS e de Styled Components para Tailwind, criei uma aplicação Vite + React simples que consiste em um carrinho de compras (clássico, né?) e adicionei os estilos inicialmente com o Styled na branch main.

Tela da aplicação MinhaLoja listando três produtos

O layout das telas foi feito somente para ter uma estilização básica da página, então desde já peço perdão pela feiura!

Esta aplicação consiste basicamente de três páginas: Home, Carrinho e Página de Produto. Além disso, criei um Layout base com a Navbar e o Footer, seguindo a estrutura abaixo:


├── eslint.config.js
├── estrutura.txt
├── index.html
├── package.json
├── package-lock.json
├── public
│   └── vite.svg
├── README.md
├── src
│   ├── App.tsx
│   ├── assets
│   │   └── react.svg
│   ├── common
│   │   ├── paths.ts
│   │   └── styles
│   │   ├── index.scss
│   │   ├── _reset.scss
│   │   ├── tokens
│   │   │   ├── _colors.scss
│   │   │   └── _font-sizes.scss
│   │   └── _variables.scss
│   ├── components
│   │   └── header
│   │   ├── footer
│   │   │   ├── footer.component.tsx
│   │   │   └── footer.module.scss
│   │   └── header
│   │   ├── header.component.tsx
│   │   └── header.module.scss
│   ├── main.tsx
│   ├── pages
│   │   ├── cart
│   │   │   ├── cart-page.module.scss
│   │   │   └── index.tsx
│   │   ├── home
│   │   │   ├── home-page.module.scss
│   │   │   ├── index.tsx
│   │   │   └── products.ts
│   │   ├── index.tsx
│   │   ├── layout.module.scss
│   │   └── product
│   │   ├── index.tsx
│   │   └── product-page.module.scss
│   └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── yarn.lock

2. Por que o SCSS?

Existem vários pontos para se analisar na hora de escolher uma ferramenta de estilização. Pensando na migração do Styled Components para uma outra, considero o SCSS uma ferramenta interessante por conta dos seguintes pontos:

2.1. Sintaxe de estilização idêntica ao do Styled Components. Por debaixo dos panos, o styled utiliza o Stylis como pré-processador de CSS o que permite que ele dê suporte à sintaxe SCSS.
2.2. Fuga do CSS-in-JS. O uso do SCSS acompanha a tendência do mercado de deixar de utilizar tecnologias mais performáticas.

2.3. Estabilidade ao longo dos anos. O Sass é uma tecnologia bastante conhecida no mercado e que não vem perdendo espaço com os anos. Abaixo, segue um print de um comparativo entre as três tecnologias mencionadas neste artigo.
Print de tela com comparativo de downloads nos últimos cinco anos obtido a partir do NPM Trends
Comparativo de downloads nos últimos cinco anos. NPM Trends, acessado em 08/04/2025.

2.4. Compatibilidade com React Server Components (RSC). É possível importar estilos globais em RSC, garantindo que a estilização ocorra do lado do server. Na parte de CSS-in-JS da documentação do Next.js é citado que:

If you want to style Server Components, we recommend using CSS Modules or other solutions that output CSS files, like PostCSS or Tailwind CSS.

2.5. CSS Modules. Com arquivos .module.scss podemos definir estilos com escopo local para um determinado módulo.

3. Instalação

Para instalar o SCSS na nossa aplicação é bem simples, basta rodar:

yarn add -D sass

OBS.: A diferença de SCSS e SASS é de sintaxe. Ambas tem as mesmas funcionalidades parecem muito entre si, entretanto o SCSS se parece mais com o CSS, fazendo o uso de chaves enquanto o SASS utiliza da identação para separar seus estilos.
https://pt.stackoverflow.com/questions/54453/qual-%C3%A9-a-diferen%C3%A7a-entre-sass-e-scss

4. Configuração

Após instalar a biblioteca na nossa aplicação, precisamos adicionar a seguinte configuração ao vite.config.ts:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import path from 'path'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "@/common/styles/variables" as *;`,
      },
    },
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
})

Enter fullscreen mode Exit fullscreen mode

Em css.preprocessorOptions.scss.additionalData, estou dizendo ao Vite que quero carregar globalmente as variáveis declaradas neste path.

5. Migrando a Home Page para SCSS

Para exemplificar o processo de migração de estilos para o SCSS, vamos pegar o exemplo da para exemplificar.

Nos trechos de códigos abaixo estão respectivamente o arquivo de renderização da tela e seu arquivo de estilos (com Styled Components):

//src/pages/home/index.tsx
import { products } from "./products";
import * as Styles from "./styles";

export const HomePage = () => {
    return (
      <Styles.Container>
        <Styles.Title>Produtos em destaque</Styles.Title>
        <Styles.ProductsGrid>
          {products.map(product => (
            <Styles.ProductCard key={product.id}>
              <Styles.ProductImage src={product.image} alt={product.name} />
              <Styles.ProductName>{product.name}</Styles.ProductName>
              <Styles.ProductPrice>{product.price}</Styles.ProductPrice>
            </Styles.ProductCard>
          ))}
        </Styles.ProductsGrid>
      </Styles.Container>
    );
  };

Enter fullscreen mode Exit fullscreen mode
// src/pages/home/styles.ts
import styled from 'styled-components';

export const Container = styled.div`
  padding: 2rem;
`;

export const Title = styled.h1`
  font-size: ${(props) => props.theme.fontSizes.lg};
  margin-bottom: 1.5rem;
`;

export const ProductsGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1.5rem;
`;

export const ProductCard = styled.div`
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 1rem;
  background-color: ${(props) => props.theme.colors.secondary};
  transition: box-shadow 0.2s;

  &:hover {
    box-shadow: 0 0 8px rgba(0,0,0,0.1);
  }
`;

export const ProductImage = styled.img`
  width: 100%;
  height: 160px;
  object-fit: cover;
  border-radius: 4px;
`;

export const ProductName = styled.h2`
  font-size: ${(props) => props.theme.fontSizes.md};
  margin: 0.5rem 0;
`;

export const ProductPrice = styled.p`
  font-weight: bold;
  color: #2c3e50;
`;
Enter fullscreen mode Exit fullscreen mode

Agora vamos ver como esta mesma estilização é feita com SCSS.

//src/pages/home/index.tsx
import { products } from "./products";
import styles from "./home-page.module.scss";

export const HomePage = () => {
    return (
      <div className={styles["container"]}>
        <h1 className={styles["title"]}>Produtos</h1>
        <div className={styles["product-grid"]}>
          {products.map((product) => (
            <div className={styles["product-card"]} key={product.id}>
              <img className={styles["product-image"]} src={product.image} alt={product.name} />
              <h2 className={styles["product-name"]}>{product.name}</h2>
              <p className={styles["product-price"]}>{product.price}</p>
            </div>
          ))}
        </div>
      </div>
    );
  };

Enter fullscreen mode Exit fullscreen mode
/*src/pages/home/home-page.module.scss*/
.container {
    padding: 2rem;
}

.title {
    font-size: $font-size-lg;
    margin-bottom: 1.5rem;
}

.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1.5rem;
}

.product-card {
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    padding: 1rem;
    background-color: $color-secondary;
    transition: box-shadow 0.2s;

    &:hover {
      box-shadow: 0 0 8px rgba(0,0,0,0.1);
    }
}

.product-image {
    width: 100%;
    height: 160px;
    object-fit: cover;
    border-radius: 4px; 
}

.product-name {
    font-size: $font-size-md;
    margin: 0.5rem 0;
}

.product-price {
    font-weight: bold;
    color: #2c3e50;
}
Enter fullscreen mode Exit fullscreen mode

6. Resultados obtidos

Com base no comparativo entre estas tecnologias, segui às seguintes conclusões:

  • A sintaxe realmente é bem similar. E isto foi um ponto muito bem pensado. Os criadores do Styled Components queriam criar uma biblioteca de estilização com baixa curva de aprendizagem, então aproveitaram a familiaridade que os desenvolvedores da época já tinham com o SCSS e pegaram esta sintaxe como base.
  • Atenção ao uso dos estilos como CSS Modules. A fim de evitar sobreposição de estilos é necessário criar os arquivos de estilo como [nome do arquivo].module.scss e importar os estilos destes arquivos como no exemplo: import styles from "./home-page.module.scss"; Tive problemas com sobreposição de estilos, pois tinha criado a classe .container em mais de um componente, porém como não estava importando de forma correta acabava que estes estilos estavam sendo compartilhados globalmente na aplicação, e não assumiam o escopo local.
  • Reúso de tokens. Talvez a maior dificuldade da migração seja a questão da migração dos seus tokens/tema para arquivos de variáveis CSS. A depender do quão desenvolvido estiver o tema de sua aplicação e sua estrutura de tokens pode ser que você tenha um esforço considerável, pois é preciso que se tenha uma certa atenção aos detalhes visto que pode impactar em várias telas e componentes de sua aplicação.

7. Conclusão

Neste artigo trago de forma resumida a minha experiência em migrar os estilos de uma aplicação simples, com poucas features. Em nível de projeto real, é preciso que você e seu time esteja bem alinhado com todos os stakeholders para salientar a importância desta migração (independente de ser com Sass ou outra ferramenta).

Neste caso, é recomendado que você alinhe com os POs para priorizar e estimar a refatoração em partes, converse com os QAs para que eles garantam a qualidade pós-alterações e também prepare um plano de migração bem estruturado, fazendo-o em partes à depender das necessidades da sua equipe.

Ainda neste artigo, não consegui me aprofundar em mais recursos trazidos pelo Sass visto que o foco foi em como migrar os estilos. Mas para te auxiliar nos estudos e na escolha, segue uma lista de features do Sass que acho uma boa de serem consideradas:

  • Mixins. Útil para reutilizar estilos ao longo da aplicação.
  • If/else. Ótima dica para trabalhar com estilos condicionais!
  • Each. Com esta regra é possível fazer um loop em uma lista ou map. Pode ser bastante útil por exemplo para criarmos variantes de componentes!

Na Parte 2, vou mostrar como migrar do Styled Components para Tailwind na prática, e comparar com os aprendizados dessa migração para SCSS.

Valeu demais por ler o artigo até aqui! Espero que seja útil na tomada de decisão do seu projeto. Caso queira trocar uma ideia, é só chamar. Sinta-se à vontade em deixar comentários e sugestões! Tamo junto e boa migração 🔥

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (1)

Collapse
 
cristiano_regobarrosfil profile image
Cristiano Rego Barros Filho

Artigo topp! Ótimo para o momento.

Image of PulumiUP 2025

Explore What’s Next in DevOps, IaC, and Security

Join us for demos, and learn trends, best practices, and lessons learned in Platform Engineering & DevOps, Cloud and IaC, and Security.

Save Your Spot

👋 Kindness is contagious

Dive into this insightful write-up, celebrated within the collaborative DEV Community. Developers at any stage are invited to contribute and elevate our shared skills.

A simple "thank you" can boost someone’s spirits—leave your kudos in the comments!

On DEV, exchanging ideas fuels progress and deepens our connections. If this post helped you, a brief note of thanks goes a long way.

Okay