A evolução do CSS: De arquivos CSS, SASS, BEM para CSS Modules até Styled Components

Eduardo Rabelo
Tableless
Published in
8 min readJan 19, 2017

--

Desde o início da internet, nós sempre tivemos a necessidade de estilizar nossos websites, CSS esteve sempre por aqui e evoluiu com os próprios passos durante esses anos, esse artigo irá levar você através dessa evolução.

Para começar, precisamos estar em sincronia sobre o que CSS é, acredito que podemos concordar que CSS é usado para descrever a apresentação de um documento escrito em uma linguagem de marcação.

Não é novidade que o CSS tem evoluído durante todo esse tempo e está bem mais poderoso hoje em dia. Mas ainda assim, é de conhecimento geral que é necessário algumas ferramentas para facilitar o uso em grandes equipes.

CSS no velho oeste

Nos anos 90, estávamos focados em criar “fancy” websites, o fator “uau” era o mais importante, estilos inline eram a regra do momento, nós não nos importávamos se os estilos pareciam diferentes, no final das contas, websites eram como pequenos brinquedos onde poderíamos colocar alguns gifs, marquees e e outras coisas horríveis (naquele época eram impressionantes), na esperança de chamar a atenção dos nossos visistantes.

Depois disso, nós começamos a criar websites dinâmicos, mas o CSS continuou uma constante bagunça, cada desenvolvedor tinha sua maneira de escrever CSS. Alguns de nós com problemas com a especificação de seletores, causando regressão visual quando código novo era introduzido, nós usávamos !important para termos certeza que nosso elemento iria ser estilizado daquela maneira. Mas isso viria a nos morder no futuro:

Todas essas má práticas se tornaram mais evidentes e problemas maiores quando os projetos cresciam em tamanho, complexidade e membros de equipe. Não ter um padrão consistente para estilizar nossos projetos se tornou um dos maiores bloqueadores para desenvolvedores experientes e inexperientes, que lutavam para achar uma maneira correta de organizar o CSS. No final, não tinha maneira certa ou errada de se fazer, nós só queríamos que o elemento ficasse ok.

SASS ao resgate

SASS transformou CSS em uma linguagem de programação descente, sendo uma ferramenta de pré-processamento que implementava aninhação de seletores, variáveis, mixins, extends e lógica em arquivos de estilos, possibilitando uma melhor organização dos arquivos CSS e, de uma certa maneira, descontruir o seu grande arquivo CSS em pequenos pedaços e em arquivos menores, o que era uma ótima coisa naquela época.

SASS, essencialmente, recebia código SCSS/SASS, pré-processava e produzia uma versão compilada contendo todo o CSS. Maneiro né? Não tão rápido, eu diria. Depois de um tempo, ficou claramente visível que, sem qualquer estratégia ou boas práticas, SASS só causava mais problemas do que ajudava.

De um dia para o outro, nós paramos de ligar para o que o pré-processador estava fazendo por baixo dos panos, acabamos apostando muito em seletores aninhados para vencer na especificação CSS e no final, o CSS gerado, era um incrível mostro!

Foi então que apareceu BEM…

BEM e a filosofia de pensar em componentes

Quando BEM entrou em cena no CSS, foi como um ar fresco que nos fez pensar em re-usabilidade e componentes. Ele trouxe uma semântica de nomenclatura que reduzia o risco de conflitos nos nomes de classes, utilizando uma simples convenção de Bloco-Elemento-Modificador. Um exemplo abaixo:

Se você analisar a marcação, rapidamente irá perceber a convenção nos nomes de classe.

Você pode ver que temos dois blocos específicos no código: .scenery e .sky, cada um deles contém sua nomenclatura de bloco. Sky é o único que contêm modificadores, podendo ser foggy, daytime ou dusk, essas são diferentes características que podem ser aplicadas ao mesmo elemento.

Vamos dar uma olhada em um pseudo-código para entender melhor:

Se quiser saber mais sobre BEM, eu recomendo que você leia esse artigo, escrito por um colega meu, Andrei Popa.

BEM é ótimo se você tem certeza que todo componente é único #reusabilidadeFTW. Com esse tipo de pensamento, alguns padrões se tornam mais evidentes, e acabamos migrando nossos “velhos” arquivos de estilos para esse novo padrão.

Mas nada é para sempre, com essa abordagem, conhecemos novos problemas:

  • Escolher um nome de classe acaba sendo um tédio (e difícil!)
  • Marcação fica um pouco inchada com todo esses nomes de classe longos
  • Você precisa, explícitamente, extender cada componente sempre que quiser reutilizá-lo
  • Marcação semântica se tornam “desnecessárias”

CSS Modules e escopo local

Alguns dos problemas que nem SASS ou BEM conseguiram resolver, é que no CSS, não há um verdadeiro conceito de encapsulamento, ficando à cargo do desenvolvedor criar um nome de classe único.

E, sendo sincero, isso é um processo que pode ser resolvido por uma ferramenta ao invés de uma convenção.

E é exatamente isso que CSS Modules resolve, ele te garante que irá criar, dinamicamente, um nome de classe único para cada estilo definido localmente, fazendo valer que não haverá regressão visual caso uma nova classe CSS seja injetada na página, todos os estilos são propriamente encapsulados.

CSS Modules ganhou popularidade rapidamente na comunidade React, e hoje em dia é comum ver vários projetos utilizando isso. Claro que existem pros e contras, mas, no geral, se provou ser um ótimo paradigma para se usar.

Mas… CSS Modules por sí só não resolve alguns problemas principais do CSS, ele apenas te mostra uma maneira de localizar suas definições: um método inteligente de gerar identificadores únicos BEM, para que você não precise pensar nisso, nunca mais (ou ao menos, pensar menos!).

Mas ele não alivia o peso da necessidade de uma boa e previsível arquitetura de estilos, que seja fácil de extender, utilizar e controlar com o mínimo de esforço.

Aqui um exemplo de como CSS Modules funciona:

Você pode ver que é apenas CSS, a diferença principal é que todos os nomes de classe estão utilizando :local() para gerar um único nome de classe, que irá se parecer com:

.app-components-button-__root-3vvFf {}

Você pode configurar o gerador, passando localIdentName como parâmetro. Ficando assim:

css-loader?localIdentName=[path][name]---[local]---[hash:base64:5]

Para melhora a nomenclatura durante o desenvolvimento. Mas não recomendo para produção pois irá gerar nome de classes muito grandes!

Este é um princípio bem simples por trás do CSS Modules. Se você olhar direito, módulos locais se tornam um jeito automático de usar a conveçãO BEM, que irá garantir um nome único sem conflito com nenhuma outra declaração na sua base de código CSS. Bem conveniente.

E nasce o Styled Components, misturando CSS no JS

Styled Components são declarações primitivas que envolvem seu componente. Elas são mapeadas para a atual marcação HTML do seu componente.

Mais ou menos assim:

Olhando de perto, um styled component é bem simples, ele usa a template literals do ES6 para definir as propriedades CSS.

Style Components disponibilizam uma maneira bem simples de reutilizar e realmente separar smart/dumb components. Criando uma API que tem acesso nativo as marcações, tanto no navegador com HTML, quanto em elementos nativo com React Native.

Você pode passar props customizadas para seu componente (ou modificadores):

Você pode ver que essas props se tornaram os modificadores, que cada instância do componente irá receber, podendo ser processado e renderizado de uma maneira diferente, irado né?

Isso nos permite produzir mais rapidamente e utilizar todo o poder do JS para processar nossos estilos enquanto temos certeza de que nosso componente continua consistente e re-usável.

Componentes principais, criando sua biblioteca de componentes

Fica aparente que nem CSS Modules ou Styled Components são soluções perfeitas, é necessário um tipo de padrão para colocar order, de maneira que cresça sem problemas.

O padrão que se concretizou, relaciona-se com componentes e a definição do mesmo separando-o totalmente de sua lógica. Criando componentes principais que, sua única razão de existência, é a reutilização pelos demais.

Um exemplo utilizando CSS Modules:

Se você olhar, não tem nada de extravagante aqui, esse componente recebe propriedades que são repassadas ao componente filho. Em outras palavras: o componente pai, transfere todas as suas propriedades para os componentes filhos.

Sendo assim, seu componente pode ser utilizado da seguinte maneira:

E aqui, um exemplo completo de um componente de botão utilizando Styled Components:

O que é interessante desse padrão, é que esse componente serve apenas como um container de definições CSS que são mapeadas a partir do componente pai. E existe uma vantagem disso:

Isso define uma API padrão de UI na qual você pode trocar componentes a qualquer momento e ainda manter sua aplicação consistente.

Dessa maneira, podemos isolar completamente o processo de design e de implementação, podendo até, fazer ambos ao mesmo tempo. Você pode ter um desenvolvedor focado na implementação e outro polindo os detalhes da UI, conseguindo uma separação total de interesses.

Falando assim, parece uma ótima solução, internamente, nós conversamos sobre essa abordagem e decidimos segui-la. E, o mais legal disso, foi que descobrimos novos paradigmas com essa abordagem.

Receptores de propriedades

São os responsáveis por escutar todas as propriedades passadas para um componente, essas funções podem ser utilizadas em qualquer componente. É um dos principais pontos para reutilização e extensão de capacidades de qualquer componente. Aqui um exemplo do que quero dizer:

Dessa maneira, você não precisa digitar o estilo de borda e margins para cada componente, salvando tempo e ajudando da manutenção (e também ritmo de layout). 🏆

Simulando Placeholder/Mixins

Em Styled Components, você pode usar o poder total do JS para criar uma infinidade de funções, que não apenas receberam propriedades de estilo, mas também, para compartilhar estilos entre componentes, um exemplo:

Componentes de Layout

Uma das coisas que identificamos que precisamos fazer logo cedo em qualquer aplicação, é a definição de layout e separação de elementos da UI. Por esse motivo, criamos alguns componentes que nos ajudam nisso.

Esses componentes se mostraram muito úteis para definir nossas estruturas de um modo seguro (e também, ajudando desenvolvedores que não estão familiarizados com técnicas de posicionamento em CSS). Um exemplo:

Você pode ver, nós temos nosso componente que recebe um width e um height como props e também, a opção horizontal, caso seja necessário mostrar a barra de rolagem no modo horizontal.

Componentes utilitários

Componentes utilitários deixam nossa vida bem mais simples e nos permitem uma grande flexibilidade. Esse é o local aonde guardamos algumas das nossas definições mais comuns.

Alguns utilitários que sempre levo comigo:

Temas

É possível criar componentes de primeira ordem para provar que podemos manter uma definição única de estilos que podem ser reutilizadas na aplicação. Armazenando elementos como palheta de cores, dinâmica de espaços, ritmo de tipografia e etc. Um exemplo:

Parte boa

  • O total poder do JS nas suas mãos, controle absoluto sobre todos os componentes da sua UI
  • Elimina a etapa de mapear nome de componentes com o atributo className (isso é feito por baixo dos panos)
  • Uma experiência de desenvolvimento ótima! (Eu recomendo você testar!) Reduzindo praticamente a zero o mapeamento mental entre elementos HTML, seletores CSS e estado/comportamento no JS.

Parte não tão boa

  • Poucos cases para exemplo em grandes produtos
  • Criado com o React em mente
  • Muito, muito novo!
  • Teste de QA tem que ser feito através de aria-label (ou adicionando uma classe apenas para isso)

Conclusão

Qualquer que seja a tecnologia que você escolher, seja ela SASS, BEM, CSS Modules ou Styled Components. Não há um substituto melhor do que uma arquitetura de estilos bem definida, onde ela seja intuitiva para outros desenvolvedores poderem contribuir na introdução de novas partes e sem o medo de “quebrar” outras.

Essa abordagem é crucial para poder escalar seu CSS de maneira saudável. Seja usando o bom e velho CSS ou BEM. A diferença principal é a linha de controle que é preciso para cada abordagem. De toda maneira, Styled Components está me provando ser uma ótima escolha para projetos React.

--

--