Explorando o SMACSS: arquitetura escalável e modular para CSS
Publicados: 2022-03-11Quando estamos trabalhando em grandes projetos ou com grupos de desenvolvedores, geralmente descobrimos que nosso código é confuso, difícil de ler e difícil de estender. Isso é especialmente verdade depois que o tempo passa e voltamos e olhamos novamente – temos que tentar estar na mesma mentalidade em que estávamos quando o escrevemos.
Então, o que muitas pessoas fizeram foi criar arquiteturas CSS para ajudar a estilizar seu código para que o CSS se tornasse mais legível. SMACSS —ou seja, Arquitetura Escalável e Modular para CSS — tem como objetivo fazer exatamente isso. É um conjunto específico de diretrizes de arquitetura CSS de Jonathan Snook que adotei.
Agora, a abordagem arquitetural do SMACSS é um pouco diferente de um framework CSS como Bootstrap ou Foundation. Em vez disso, é um conjunto de regras, mais como um modelo ou guia. Então, vamos mergulhar em alguns padrões de design CSS para descobrir como podemos usá-los para tornar nosso código melhor, mais limpo, mais fácil de ler e mais modular.
Toda estrutura de projeto SMACSS usa cinco categorias:
- Base
- Esquema
- Módulos
- Estado
- Tema
Base
No SMACSS, os estilos básicos definem como um elemento deve se parecer em qualquer lugar da página. Eles são os padrões. Se você estiver usando uma folha de estilo de redefinição, isso garante que seus estilos resultantes sejam os mesmos em todos os navegadores, apesar das diferenças entre seus padrões CSS básicos internos e codificados.
Em um estilo base, você deve incluir apenas seletores de elementos simples, ou aqueles com pseudoclasses, mas não com seletores de classe ou ID. (Você deve ter um bom motivo para colocar classe ou ID dentro dele, talvez apenas se estiver estilizando os elementos de um plug-in de terceiros e precisar substituir o estilo padrão para esse elemento específico.)
Aqui está um exemplo de como uma unidade de arquivo base deve se parecer:
html { margin: 0; font-family: sans-serif; } a { color: #000; } button { color: #ababab; border: 1px solid #f2f2f2; }Portanto, ele deve incluir tamanhos, margens, cores, bordas padrão e quaisquer outros valores padrão que você planeja usar em seu site. Sua tipografia e seus elementos de formulário devem ter estilos unificados que aparecem em todas as páginas e dão uma sensação e aparência de que fazem parte do mesmo design e tema.
SMACSS ou não, eu recomendo evitar o uso de !important o máximo possível, e não usar aninhamento profundo, mas falarei mais sobre isso mais adiante neste post. Além disso, se sua prática é usar reset CSS, este é o lugar onde você deve incluí-lo. (Prefiro usar Sass, então apenas o incluo no topo do arquivo, em vez de ter que copiá-lo ou referir-se a ele separadamente do elemento <head> de cada página.)
Esquema
Os estilos de layout dividirão a página em seções principais - não seções como navegação ou talvez o acordeão, por exemplo, mas divisões de nível superior:
Esses layouts conterão vários módulos CSS como caixas, cartões, listas não ordenadas, galerias e afins, mas falarei mais sobre módulos na próxima seção. Vamos considerar um exemplo de página da Web para ver o que podemos dividir em layouts:
Aqui temos header, main e footer. Esses layouts possuem módulos como links e logotipo no cabeçalho na parte superior, caixas e artigos no principal e links e direitos autorais no rodapé. Costumamos dar aos layouts um seletor de ID, pois eles não se repetem na página e são únicos.
Além disso, você deve prefixar as regras para estilos de layout com a letra l para distingui-las dos estilos de módulo. Normalmente, aqui você estiliza coisas específicas ao layout, como bordas, alinhamentos, margens, etc. Além disso, o plano de fundo dessa parte da página pode fazer sentido, mesmo que não pareça ser tão específico do layout.
Aqui está um exemplo de como deve ficar:
#header { background: #fcfcfc; } #header .l-right { float: right; } #header .l-align-center { text-align: center; }Você também pode adicionar esses auxiliares para alinhamentos que podem ser usados para posicionar facilmente os elementos apenas adicionando a classe apropriada ao filho ou para alinhar seu texto.
Para outro exemplo, você pode usar algumas margens padrão em uma caixa de layout, como .l-margin com uma margem de 20px . Então, onde quer que você queira preenchimento para algum contêiner, elemento, cartão ou caixa, basta adicionar a classe l-margin a ele. Mas você quer algo reutilizável:
.l-full-width { width: 100%; }Não é algo acoplado internamente assim:
.l-width-25 { width: 25px; }Eu quero ter um momento para falar sobre convenções de nomenclatura no SMACSS. Se você nunca ouviu falar do conceito de namespace em CSS, é basicamente adicionar o nome ao início de outro elemento para ajudar a distingui-lo de qualquer outra coisa. Mas por que precisamos disso?
Não sei se você já se deparou com o seguinte problema. Você está escrevendo CSS e tem um rótulo em alguma coisa - você coloca os estilos que quiser e chama sua classe de .label . Mas então você chega a outro elemento mais tarde, e você também quer que seja .label , mas com um estilo diferente. Portanto, duas coisas diferentes têm o mesmo nome – um conflito de nomenclatura.
O namespace ajuda a resolver isso. Em última análise, eles são chamados da mesma coisa em um nível, mas têm um namespace diferente - um prefixo diferente - e, portanto, podem representar dois estilos diferentes:
.box--label { color: blue; } .card--label { color: red; }Módulo
Como mencionei anteriormente, os módulos SMACSS são pedaços menores de código que são reutilizáveis na página e fazem parte de um único layout. Essas são partes do CSS que queremos armazenar em uma pasta separada, pois teremos muitas delas em uma única página. E à medida que um projeto cresce, podemos dividir usando as melhores práticas de estrutura de pastas, ou seja, por módulos/páginas:

Então, no exemplo anterior, tínhamos um artigo, que pode ser um módulo por conta própria. Como o CSS deve ser estruturado aqui? Devemos ter uma classe .article que pode ter elementos filho title e text . Então, para poder mantê-lo no mesmo módulo, precisamos prefixar os elementos filhos:
.article { background: #f32; } .article--title { font-size: 16px; } .article--text { font-size: 12px; } Você pode notar que estamos usando dois hífens após o prefixo do módulo. A razão é que às vezes os nomes dos módulos têm duas palavras ou seus próprios prefixos como big-article . Precisamos ter dois hífens para dizer qual parte dele é o elemento filho - por exemplo, compare big-article-title com big-article--title e big-article--text .
Além disso, você pode aninhar módulos dentro de módulos se um módulo específico ocupar uma grande parte da página:
<div class="box"> <div class="box--label">This is box label</div> <ul class="box--list list"> <li class="list--li">Box list element</li> </ul> </div> Aqui, neste exemplo simples, você pode ver que a box é um módulo e a list é outro módulo dentro dela. Então list--li é filho do módulo list e não do box . Um dos conceitos-chave aqui é usar dois seletores no máximo por cada regra CSS, mas na maioria dos cenários ter apenas um seletor com prefixos.
Dessa forma, podemos evitar a duplicação de regras e também ter seletores extras em elementos filhos com os mesmos nomes, melhorando assim a velocidade. Mas também nos ajuda a evitar o uso das indesejadas regras de estilo !important , que são um sinal de projetos CSS mal estruturados.
Bom (observe o seletor único):
.red--box { background: #fafcfe; } .red-box--list { color: #000; }Ruim (observe a repetição nos seletores e o método de referência sobreposto):
.red .box { background: #fafcfe; } .red .box .list { color: #000; } .box ul { color: #fafafa; }Estado
O que o estado define no SMACSS é uma maneira de descrever como nossos módulos se parecem em diferentes situações dinâmicas. Portanto, esta parte é realmente para interatividade: queremos um comportamento diferente se um elemento for considerado oculto, expandido ou modificado. Por exemplo, um acordeão jQuery precisará de ajuda para definir quando você pode ou não ver o conteúdo de um elemento. Isso nos ajuda a definir o estilo de um elemento em um momento específico.
Os estados são aplicados ao mesmo elemento que o layout, portanto, estamos adicionando uma regra adicional que substituirá as anteriores, se houver. A regra de estado tem precedência, pois é a última na cadeia de regras.
Assim como nos estilos de layout, costumamos usar prefixos aqui. Isso nos ajuda a reconhecê-los e a dar-lhes prioridade. Aqui usamos o prefixo is , como em is-hidden ou is-selected .
<header> <ul class="nav"> <li class="nav--item is-selected">Contact</li> <li class="nav--item">About</li> </ul> </header> .nav--item.is-selected { color: #fff; } Aqui, !important pode ser usado, pois state é frequentemente usado como uma modificação de JavaScript e não em tempo de renderização. Por exemplo, você tem um elemento oculto no carregamento da página. Ao clicar no botão, você deseja mostrá-lo. Mas a classe padrão é assim:
.box .element { display: none; }Então, se você apenas adicionar isso:
.is-shown { display: block; } Ele permanecerá oculto mesmo depois que você adicionar a classe .is-shown ao elemento via JavaScript. Isso ocorre porque a primeira regra tem dois níveis de profundidade e a substituirá.
Então você pode definir a classe de estado assim:
.is-shown { display: block !important; }É assim que distinguimos os modificadores de estado dos de layout, que se aplicam apenas no carregamento inicial de uma página. Isso funcionará agora, mantendo as vantagens dos seletores mínimos.
Tema
Este deve ser o mais óbvio, pois é usado para conter as regras das cores primárias, formas, bordas, sombras e afins. Principalmente estes são elementos que se repetem em todo um site. Não queremos redefini-los cada vez que os criamos. Em vez disso, queremos definir uma classe única que só adicionamos posteriormente a um elemento padrão.
.button-large { width: 60px; height: 60px; } <button class="button-large">Like</button>Não confunda essas regras de tema SMACSS com as básicas, pois as regras básicas visam apenas a aparência padrão e tendem a ser algo como redefinir as configurações padrão do navegador, enquanto uma unidade de tema é mais um tipo de estilo onde dá a aparência final, exclusivo para este esquema de cores específico.
As regras de tema também podem ser úteis se um site tiver mais de um estilo único ou talvez alguns temas usados em estados diferentes e, portanto, podem ser facilmente alterados ou trocados durante alguns eventos em uma página, por exemplo, com um botão de mudança de tema. No mínimo, eles mantêm todos os estilos de tema em um só lugar para que você possa alterá-los facilmente e mantê-los bem organizados.
Metodologias de Organização CSS
Abordei alguns dos principais conceitos dessa ideia de arquitetura CSS. Se você quiser saber mais sobre esse conceito, visite o site oficial do SMACSS e se aprofunde nele.
Sim, você provavelmente pode usar metodologias mais avançadas como OOCSS e BEM. Este último cobre quase todo o fluxo de trabalho front-end e suas tecnologias. Os seletores BEM podem funcionar muito bem para algumas pessoas, mas alguns podem achá-los muito longos e sobrecarregados, e também muito complicados de usar. Se você precisa de algo mais simples que seja mais fácil de assimilar e incorporar ao seu fluxo de trabalho—e também algo que defina regras básicas para você e sua equipe—SMACSS é a solução perfeita.
Será fácil para os novos membros da equipe não apenas entender o que os desenvolvedores anteriores fizeram, mas também começar a trabalhar instantaneamente, sem diferenças no estilo de codificação. SMACSS é apenas uma arquitetura CSS e faz o que diz na lata - nada mais e nada menos.
