Parece que https://no-css.com/ é realmente um projeto! ahaha

Construindo uma aplicação sem CSS — Os altos e baixos sobre isso

Em um artigo recente no Smashing Magazine, Krasimir Tsonev escreveu sobre CSS em JavaScript. Ele fala sobre o conceito de não usar arquivos CSS e, ao invés disso, definir todos os seus estilos em JavaScript, usando inline-styles.

O artigo em si é bem interessante, mas os comentários são mais interessantes ainda, principalmente esses dois primeiros:

Parece que Bob poderia ter salvo seu tempo e ter listado algumas coisas que ele acha que são boas. De verdade, abandonar de vez os arquivos CSS, não é para qualquer um.

Acredito que o gráfico abaixo possa te ajudar a tomar essa decisão:


A psicologia da mudança

Naturalmente, muitas pessoas irão resistir há essa idéia. Caso você pense dessa maneira, tente imaginar o seguinte: Separe o aborrecimento de aprender uma nova tecnologia do amor incondicional que desenvolvedores tem ao fazer algo diferente do padrão.

Quer uma dica? Imagine que tudo fosse o contrário, que usar inline-styles fosse o padrão e, de repente, alguém falasse que você deveria usar um arquivo CSS.

Parece doido, não?


Como tudo começou

O ano era 2016. O mês era Maio. Eu estava começando um novo projeto e eu poderia usar o que me desse na telha. Liberdade com grandes responsabilidades, lembra alguém?

Agora é Julho, e o projeto está “terminado” (sempre falta algo, certo?), então eu pensei: “acho que eu poderia contar o que descobri”.

Alerta de spoiler: Depois de dois meses de altos e baixos, eu não tenho uma opinião forte sobre usar ou não inline-styles, mas no final desse post, eu espero que, ao menos, sirva de inspiração para você tentar algo novo ou ter bons argumentos para não usar isso no seu projeto!


Uma nova esperança com essa abordagem

Como disse, nós não iremos usar CSS, na verdade, só iremos remover duas etapas de todo o processo CSS do projeto:

  • Arquivos SASS/CSS
  • Nomes de classes nos arquivos HTML

Nós ainda vamos usar declarações CSS, afinal, elas que definem nossos estilos e nos fazem argumentar com designers que esse 1px pode ficar de fora.

E como é que é?

Na era de ouro, desenvolvedores criavam arquivos CSS com seletores e suas declarações. Em seguida, criavam arquivos HTML com declarações de classes. Os estilos são aplicados por causa do nome das classes no elemento HTML que são iguais aos seletores CSS.

O que eu disse?

Se não usarmos um arquivo CSS, nosso modelo ficaria assim:

Pergunte a qualquer desenvolvedor que não conhece CSS, qual dos dois exemplos acima faz mais sentido?

Vamos listar alguns pontos:

A parte boa

  • Configuração do seu projeto/build fica mais simples
  • Nenhuma configuração para SASS (ou qualquer pré-processador CSS)
  • Estilos são mais integrados com a lógica da aplicação
  • Uma linguagem a menos no projeto
  • Imagens como backgroundImage (mais sobre isso a seguir)
  • Variáveis podem ser usadas em JavaScript

A parte ruim

  • Não poder usar :before ou :after (ou qualquer pseudo elemento ou classe)
  • Ter um elemento filho mudando seu estado no efeito de :hover é meio complicado (mais sobre isso a seguir)
  • É difícil dizer o que é o que no DevTools do navegador
  • É difícil experimentar novos estilos no DevTools e ver seus efeitos no geral
  • Em qualquer lugar que você tente selecionar um elemento usando uma classe, ex: .Header, não irá funcionar
  • Hot Module Replacement, não funciona para estilos em JavaScript
  • Media queries necessitam uma biblioteca específica

Nosso cenário, um projeto real, na vida real

Vamos ao que interessa, código, aqui vai um exemplo:

Para executar esse código, não é necessário nenhuma outra biblioteca, é puramente React.

É um exemplo simples, mas mostra algo bem poderoso, a composição de estilos (usando o operador spread). Claro, você pode combinar estilos em CSS e a ordem dos nomes das classes não é importante. Na verdade, no CSS, elas são importantes sim, você está prestando atenção? Confuso né?

Agora, vamos ver algo mais complexo, mas primeiro…


Nosso projeto, um pouco mais sobre Malla

O código nesse exemplo é um pedaço do Malla, um projeto que eu venho construindo nos últimos dois meses. Malla é um aplicativo para armazenar e atualizar textos para seu website.

É como um leve CMS, mas ao invés de armazenar dados em um banco de dados, você “escreve” pequenas caixas de texto na tela. Você acaba tendo como resultado, algo parecido com um wireframe, mas, tem uma API para acessar todo esse texto.

Isso quer dizer que existem algumas regras complexas para o usuário adicionar, editar ou arrumar essas pequenas caixas na tela.

No Malla, existe esse conceito de "box", que armazenam textos. Esse box, contém dois tipos e pode receber um de três tipos de estado.

Você pode se inscrever no Malla aqui

Para deixar bem claro, esse "box" é criado a partir de vários elementos. Se estivéssemos usando CSS, seria algo como:

  • Uma classe .box como elemento principal em uma div
  • Quatro classes modificadoras, como .box--label.box--moving, etc
  • Seletores como .box.box--moving .handle { display: “block”; }
  • Alguma lógica para configurar as posições left e top baseado nas props
  • Alguma lógica para adicionar / remover as classes modificadoras

Em poucas palavras, nós temos 4 coisas acontecendo aqui:

  1. Uma classe base para CSS
  2. Classes condicionais/modificadoras (o M no BEM)
  3. JavaScript para adicionar/remover classes baseado em algum estado
  4. JavaScript para configurar as posições left/top no atributo style do nosso elemento

Isso parece bem normal. Se você for como eu, provavelmente nunca parou para pensar o quão complicado isso é.

Cara, é muita coisa acontecendo ao mesmo tempo

Quando eu parei de usar classes, eu percebi a beleza e quão limpo essa estrutura fica com JavaScript. Não precisamos mais de todo aquele cruzamento de linguagens e símbolos diferentes para encontrar a classe desejada.

É apenas o bom e velho JavaScript.

Aqui um exemplo simples de um botão que deve ficar cinza quando estiver desabilitado:

Se você ainda não conhece o operador spread (…props.style), apenas imagine que ele “explode” o objeto — ou seja, cada chave/valor é “puxada” para o objeto acima — é uma maneira de clonar ou misturar um objeto em outro. Você pode usar Object.assign() para obter a mesma funcionalidade.

É uma abordagem parecida com o classnames, onde adicionamos estilos condicionalmente, mas aqui, ela é bem mais direta.

E vamos a outro exemplo um pouco mais complexo, uma box que muda sua aparência baseada em diferentes coisas.

Perceba as declarações if, cada uma delas aplica um certo tipo de estilo a vários componentes dessa box (alterando os valores do objeto styles).

Perceba no início, que estamos clonando o objeto baseStyles, ou seja, podemos exportar esses estilos para serem usados em outro arquivo, ou mesmo clonar estilos de outro módulo.


Um punhado de tudo, o que deu bom, o que deu ruim

Apesar de todos esses exemplos e pequenos trechos de explicação, não é tão simples entender a lógica dessa mudança e o que trouxe de bom ou ruim no meu fluxo de desenvolvimento, vou tentar citar outros pontos:

Parte boa: Características do SASS simplesmente usando JavaScript

Eu acredito que em JavaScript, é mais simples criar uma função para unir objetos. Não quero dizer que mixins em SASS são difíceis. Alguns exemplos:

  • O mixin pos recebe quatro argumentos e retorna nossas declarações CSS para left, top, width e height (usando as shorthand properties do ES2015 no exemplo acima)
  • O mixin shadow retorna o box-shadow necessário baseado no estilo passado e, caso nenhum seja passado, retorna um estilo padrão (usando os default arguments do ES2015)
  • O objeto inputStyle, é um conjunto de declarações de estilos comuns na nossa aplicação. Algo como os placeholders em SASS.

Parte ruim: Herança

As vezes eu sinto muita falta do C do CSS. Eu quero que todas as minhas tags p tenham uma line-height de 1.6, exceto no container do markdown que estou parseando, aqui eu quero que todos os p tenham um line-height de 1.

Sem doce para você hoje. Eu poderia usar uma biblioteca como o Radium e inserir uma tag de estilo que contenha essas declarações, e então usar nome de classes novamente, apenas para o meu container markdown.

Claro, eu posso fazer isso, mas eu não preciso fazer isso. Esse é um dos pontos que me faz pensar em usar CSS em outros projetos. Porém, tem sido um problema apenas nesse caso do markdown.

Parte boa: Configurações mais simples

Webpack é como uma criança de quatro anos de idade que é incrível tocando piano, mas está sempre chorando e irritando todo mundo. Eu respeito a complexidade da ferramenta, mas quanto menos tempo eu gastar configurando ela, melhor. E ter praticamente zero de complexidade para criar o fluxo de trabalho para meus estilos, é uma coisa boa!

Parte ruim: Declarações :pseudo do CSS

Nessa aplicação, tem apenas uma parte que eu gostaria de usar o pseudo seletor :before. Mas não poder usa-lo foi um pé no saco!

Ah, se você quiser usar :hover irá precisar de uma biblioteca externa (Eu gostei de usar Radium, que nos possibilita usar media queries também) e o item que você está usando :hover deve conter uma chave ou id único, outro ponto, :hover dispara uma renderização do componente, o que pode complicar outras coisas que estão acontecendo ao mesmo tempo.

Um argumento positivo disso tudo é, se você está desenvolvendo aplicações touch-first, dificilmente você irá depender de :hover para criar interações.

Parte boa: Lógica integrada

Toda a lógica e modificações estão no mesmo lugar. Não estou adicionando/removendo classes que existem em um outro arquivo que depende de uma declaração global. Eu estou dizendo, explicitamente, se esse componente for selecionado, aplique a cor de background X.

Parte ruim: Sem “hot reloading”

Talvez seja possível, mas, até esse ponto da minha vida, eu não consegui fazer funcionar hot reloading de CSS (o navegador só substitue o arquivo CSS sem precisar recarregar a página) dentro de arquivos JavaScript. Todos os meus estilos estão dentro de arquivos .jsx, junto dos componentes, infelizmente essa é uma parte que não foi resolvida até o momento.

Parte boa: Imagens como backgroundImage

CSS tem várias propriedades para lidar com imagens de um jeito bem inteligente (size, repeat, etc). Se você estiver adicionando uma imagem (uma imagem de perfil, por exemplo) via JavaScript e usando o bom e velho CSS, você provavelmente pensará em usar uma tag , que no final, não pode utilizar essas propriedades. Quando estamos trabalhando com estilos em linha, mudar a propriedade background-image não é diferente de mudar o valor do atributo src da tag .

Parte ruim: Classes CSS fazem outras coisas

Quando você tem o seu DevTools aberto e está debugando uma árvore HTML bem aninhada, é bem útil ver claramente o nome de classe daquele elemento, tais como ”.article-container ou .picture-frame. Em alguns momentos eu achei frustante não ter classes, imagine que, eu quero mudar o padding da classe .button e ver isso refletido em todos os componentes. Isso não vai acontecer, porque se você alterar um botão, só esse botão irá mudar. Se eu não estivesse usando esse projeto como experimento, eu não iria gostar tanto de não ter nome de classes.

Parte boa: Variáveis do JavaScript

Isso tem sido um problema em vários projetos que trabalhei. Eu tenho algumas variáveis (sério, eu deveria chamar elas de constantes) no SASS para coisas do tipo small-padding: 12px ou animation-duration: 150ms. Parece tudo muito bom, mas quando você precisa fazer a mesma coisa no arquivo JavaScript para combinar com suas constantes do SASS, não é tão bom assim, manter isso em arquivos diferentes é um problema constante. Ter tudo acoplado apenas no JavaScript, nos liberta dessa contínua sincronização de declarações.

Parte boa: Nenhuma configuração para pré-processadores CSS

Se você não usa SASS, você pode pular esse item.

Depois de tudo configurado, SASS é ótimo! Porém, é uma besta gigante. Claro que, se você estiver usando sistemas *NIX e realmente não tem interesse em saber como isso funciona em Windows, você pode pular esse item também!

Mas, para Windows, isso chega a ser ridículo. Todas as dependências que eu tenho no meu projeto, todas elas irão funcionar em Windows, sem nenhum problema, é só clonar o repositório e pronto. Exceto SASS. Para configurá-lo, você precisa do Visual Studio (!), ferramentas de desenvolvimento C++ e Python. Deus te ajude caso você já tenha alguma versão dessas ferramentas instalada. Semana passada a nova versão do npm não estava funcinando com a versão mais recente do Visual Studio, algo relacionado com node-gyp. Eu não sei como node-gyp funciona, e nem quero saber (e acredito que as pessoas que irão contribuir no meu projeto tão não precisam saber).

Como você pode ver, não usar SASS, remove algumas complexidades.


Ufa, mas e aí, vai ou racha?

Apesar de ter encontrado vários problemas (ou talvez, hábitos de cachorro velho que são difíceis de mudar) nessa mudança de paradigma, acho bem difícil eu te dizer que você deve abandonar seus arquivos CSS e colocar todos os seus estilos em JavaScript.

Porém, depois dessa experiência, a idéia de combinar seletores de um arquivo CSS com os nomes de classes em arquivos HTML, também me parece errado.

Uma analogia (bem ruim por sinal) seria: É como crescer em uma fazenda onde só se bebe leite que vem direto da vaca. Um dia você vai na casa de um amigo na cidade e experimenta leite pasteurizado. Você fica deslumbrado e imagina várias possibilidades. Claro, você pode voltar a beber leite que vem direto da vaca, mas você vai ficar com aquela pulga atrás da orelha de que algo não está tão certo sobre isso.

Se eu começar um projeto particular hoje, eu escreveria meus estilos em JavaScript. Se eu começar um projeto para uma empresa com um time de desenvolvedores, eu usaria o bom e velho CSS.

Minha recomendação para você?

Faça o que você quiser.


Obrigado por ter lido até aqui, se você gostou do post, manda um 💚 e compartilha no Twitter! Valeu! 🙏🏼