Fabiano Nunes // @fab_tc

Sobre CSS

No ano passado, comecei a reescrever algumas folhas de estilos. Não por que estavam mal elaboradas, mas porque não eram reutilizáveis.

Meu objetivo era adotar na área de design os mesmos princípios que os programadores estudam desde o primeiro hello world!.

Como ponto de partida, vou utilizar um trecho css sugerido por um colega:

[href$=".zip"]:before, [href$=".gz"]:before {
   content: '\E004'; /* unicode for the zip folder icon */
}

Embora seja um método muito inteligente e bem elaborado, é uma das técnicas que tento combater. À primeira vista, são uma mão na roda. Porém, além de quebrarem alguns princípios, podem causar problemas que só serão contornados com a quebra de outros princípios.

Seguem alguns exemplos.

Single Source of Truth

Ao configurar como se comportam todos os elementos que combinem com [href$='zip'], interferimos na autonomia de outros componentes, já que, implicitamente, duplicamos as regras que os definem.

Um determinado componente afetado por esse seletor, a partir de agora, possui dois comportamentos: um global e um específico, ambos localizados em pontos distintos da base de código.

/* callout.css */
.Callout--special:before {
  content: 'olá!';
  border: 1px solid red;
}
<a class="Callout Callout--special" href="teste.zip">Download aqui</a>

Uma vez que não é possível acumular dois pseudos-elementos, um dos :before vai perder. A depender da especificidade de cada um, podemos ter um cenário não desejado por nenhuma das regras: um \E004 com borda vermelha.

A apropriação implícita de um :before condicionou inesperadamente um estilo a um elemento.

Explicit is better than implicit

Um comportamento implícito reduz invariavelmente sua previsibilidade.

<a href="http://um_encurtador_de_url_qualquer/Jh6&kJzip">Arquivo PDF</a>
<a href="http://meu_servidor/stream">Arquivo ZIP</a>

No primeiro caso, temos um falso positivo; no segundo, um falso negativo.

Immutability

Imutáveis são aqueles objetos que, depois de criados, não podem ter seus estados alterados.

Não vejo princípio mais útil que este para um CSS de larga escala.

Componentes imutáveis são confiáveis, são agnósticos à sua localização no DOM, são previsíveis e simplificam o seu entendimento. Quando uma classe é global mas não tem o intuito de ser global (que é o caso em questão), ela pode desfazer essa imutabilidade.

Aqui, o componente .Callout--special foi alterado por um agente externo, fora de seu escopo e de seu alcance.

Open/Closed (adaptado à realidade CSS)

As definições devem ser permitir extensões (open), mas coibir modificações (closed).

Imagine que você seja um consumer de duas bibliotecas css.

  • superultra-2.2.2.css, que comporta o trecho sugerido; e
  • framework_embutido_no_CMS-9.9.9.css, que comporta o .Callout.

Das duas uma: (i) ou você modifica um desses arquivos (que não são seus) e mantém um fork, ou (ii) cria um arquivo .css e adiciona a seguinte linha:

/* o odiado !important reativo */
.Callout--special:before {
  content: 'olá!'!important;
}

Acabamos de modificar dois comportamentos: aquele que deveria ser global (pois deixará de ser \E004) e o específico (que não deveria ser !important).

Alternativas

Seguem algumas alternativas. Elas podem parecer pouco práticas, mas, na minha opinião, são flexíveis, reutilizáveis e de fácil entendimento.

<a href="/meu-arquivo.zip">
  <span class="glyphicon glyphicon-package"></span>
  Arquivo
</a>
<a class="Callout Callout--pdf" href="/meu-relatorio.pdf">
  Relatório
</a>
<a class="callout callout-pdf" href="/meu-relatorio.pdf">
  Relatório
</a>

Desafios

Sintaxe

É o principal desafio. Eu nunca imaginaria que uma letra maiúscula causaria tanta controvérsia.

😀 p ~ li > ul + p > div > a ~ b:first-child(:not(div + p)) { ... }

😀 #id { ... }

😱 .Callout { ... }

Confusão de conceitos

Dizem que ‘essa classe não é semântica!!!’, mas veneram o Bootstrap.

  • .row é semântica?
  • .col-offset-xs-12 .col-pull-sm-5 é semântica?
  • .pull-right .hidden-xs é semântica?
  • .clearfix é semântica?
  • <nav class="nav navbar navbar-nav navbar-default collapse navbar-collapse"/> é semântica?

Quer saber o que eu acho? Sigo o relator:

“(…) Not all semantics need to be content-derived. Class names cannot be ‘unsemantic’. Whatever names are being used: they have meaning, they have purpose” – Nicolas Gallagher

Estamos em 2016. Aquela época de CSS Zen Garden já passou. Há 13 anos!!!

É isso

Escrevi demais. E nem abordei todos os princípios aplicáveis, tais como:

  • Don’t repeat yourself
  • Single Responsability Principle
  • KISS

Temos uma variedade de portais, cada qual com seu framework, cada qual com seu grupo de desenvolvedores. É difícil implementar uma regra geral que se encaixe em todos os workflows. Não acredito que essa abordagem apresentada seja definitiva, mas é um começo.

Referências

  • Nicole Sullivan [OOCSS] @stubbornella
  • Lea Verou [Secrets of CSS ] @leaverou
  • Jonathan Snook [SMACSS] @snookca
  • Harry Roberts [inuitcss] @csswizardry
  • Nicolas Gallagher [suitcss] @necolas
  • Yandex [BEM] @bem_en