CSS

29 jan, 2016

A simplicidade da especificidade

Publicidade

Tudo bem eu já entendi. “Especificidade” é uma palavra grande. Ela também parece ser um conceito muito complicado, e pode ser para muitos de vocês considerada, na melhor das hipóteses, desnecessária, um incômodo inesperado na pior das hipóteses. Isso levanta a questão:

Será que realmente precisamos de especificidade em CSS?

Sim. Nós precisamos.

Você provavelmente não está convencido. Acho que vou ter que começar a ser mais específico sobre por que precisamos de especificidade. Para fazer isso, eu quero que você limpe completamente sua mente sobre o que você acha que é a especificidade. Vamos começar a tabula rasa.

O que é especificidade?

A especificidade é o quão específica uma regra é. Eu sei que parece tautológica, mas é tão simples quanto isso. E se você pensar sobre isso, faz sentido. Se alguém lhe disser para conseguir uma cabra, ele não estará sendo muito específico. Existem muitos tipos de cabras, e eles são todos fantásticos. Agora, se alguém lhe diz para obter uma cabra preta, ele está sendo mais específico sobre o que ele quer. Ou até mesmo uma cabra branca irlandesa com dois chifres. Agora está ficando realmente específico. Isso é alguém que realmente sabe que tipo de cabra gosta.

Mas especificidade é realmente complicado/difícil/estranho para calcular.

Não, não é. Se você pode contar até 10, você pode calcular especificidade. E, esperamos, que você nunca tenha que contar até mais que 5, no máximo. Especificidade só parece difícil de calcular porque a forma como muitas fontes ensinam leva em conta todas as possíveis maneiras que você pode formar seletores.

Vamos dizer que nós temos uma amiga desenvolvedora incrível, que está denominando todas as nossas cabras. Ela pode começar denominando um div, mas isso não é muito específico! Há um número finito de tipos de elementos, tais como div, span, section ou p; eles aparecem em todos os lugares em nosso HTML, e eles nos limitam muito.

Ok, ela diz que vai deixar claro que estamos denominando cabras usando o seletor .my-goat. Agora estamos chegando a algum lugar. Vamos dizer que seu seletor original pertence ao grupo “not-really-specific”, e que o seletor de classe .my-goat pertence ao grupo “pretty-specific”. Você pode ver para onde estamos indo com isso.

// specificity: 0 0 1
div {
  // styles...
}

// specificity: 0 1 0
.my-goat {
  color: white;
  // styles...
}

Opa, o que está acontecendo com esses números? Eu sou ruim em matemática!

Não se preocupe! Lembra os nossos grupos? Do mais específico para o menos específico (da esquerda para a direita), temos três grupos:

  • Realmente, realmente muito específico (Really, really freakin’ specific)
  • Consideravelmente específico (Pretty specific)
  • Não muito específico (Not that specific)

É só acrescentar os seletores que pertencem a cada categoria, e você começa a sua especificidade. Classes são muito específicas, mas elementos (tipos) não são tão específicos. E, você provavelmente adivinhou, IDs são realmente, realmente muito específicas. Tão específicas que apenas uma delas existe em nosso documento HTML. Assim, #this-exact-goat é definitivamente mais específico do que qualquer número de seletores de classe para descrever qual cabra(s) que estamos falando.

Tudo bem, nossa desenvolvedora assume que as cabras são geralmente brancas, razão pela qual ela declarou color: white; na nossa classe .my-goat. Justo; quando pensamos em cabras, elas são geralmente brancas. Mas e se eu quiser me referir a uma cabra preta?

// specificity: 0 2 0
.my-goat.-black {
  color: black;
}

Ok, isso se parece com a nossa classe original. Só que agora ela nos deu duas classes: .my-goat e .-black.. Obviamente, se ela está nos dando duas coisas (classes) para descrever uma cabra, ela está ficando muito específica sobre o tipo de cabra. Perceba que agora temos duas maneiras muito específicas de selecionar a nossa cabra, a partir dessas duas classes. Mesmo se você não é bom em matemática, parece bastante claro que 0 2 0 vence 0 1 0.

* A propósito, estou usando o sistema RSCSS de nomenclatura. Você deve dar uma olhada nele; é realmente intuitivo! Você pode facilmente adaptá-lo para BEM ou qualquer outra coisa. Eu acho.

Agora a melhor coisa sobre isso: a ordem da fonte dessas regras não importa! Minha cabra more-specific pode aparecer antes ou depois da minha cabra less-specific, e eu ainda terei exatamente o que eu espero. É por isso que nossa amiga desenvolvedora é incrível. Ela está fazendo o nosso CSS explícito, flexível e reutilizável.

Especificidade fica ainda mais flexível do que isso, enquanto se mantém intuitiva. Vamos dizer que você quer descrever uma cabra que está dentro de uma casa. Você ainda está sendo específico sobre que tipo de cabra você está procurando, por isso .my-house > .my-goat (especificidade 0 2 0) ainda é mais específico do que apenas descrever uma cabra.

Ou e se você está descrevendo uma cabra preta que está no estado hover? Tipo, .my-goat.-black:hover? A especificidade aqui agora é 0 2 1, porque está descrevendo o estado de algo, estar :hovered não é muito específico. Está na mesma categoria de um tipo de elemento simples – muitas coisas podem estar :hovered. Ainda assim, você está sendo um pouco mais específico do que somente descrevendo uma cabra preta.

Coisas que você deve saber

Falamos muito, por isso é hora de conversar a sério. Se você ainda está dizendo a si mesmo que as questões de ordem da fonte importam, e especificidade ainda é complicado, e você está preocupado com a substituição de estilos, e você precisa adicionar hacks estranhos para chegar ao :root do problema, e…

Eu quero que você pare por um momento e esqueça tudo o que você sabe sobre CSS. Mantenha a mente aberta.

Ok, não tudo. Mas estas coisas:

Seletores são como variáveis ​​globais.

Não, eles não são. CSS é uma linguagem específica de domínio, declarativa, para estilizar coisas, e não uma linguagem de programação. Pare de pensar neles como variáveis. Eles são seletores que dizem “ei, aplique essas declarações a esses elementos”. É como JSON para estilos, e ninguém está dizendo que JSON é cheio de variáveis ​​globais. Caramba, você pode até escrever folhas de estilo como objetos JSON (mas você não deve. Sério.).

CSS é estranho, porque ele não se comporta como <inserir código imperativo aqui>.

Mais uma vez, o CSS não é uma linguagem de programação. E, mesmo que fosse, ele definitivamente não é uma linguagem imperativa (mas o quão legal seria o CSS como uma linguagem declarativa, funcional?). Se você está codificando CSS como “faça primeiro A, e depois faça B”, você está fazendo errado. CSS é mais como “A é isso, e B é isso”.

Posso substituir estilos da mesma especificidade, declarando-os mais tarde na folha de estilo.

Sim, mas você não deve. O CSS declarativo bem arquitetado não é dependente de ordem da fonte. Se duas coisas da mesma especificidade têm estilos conflitantes, então algo está errado na forma como você está definindo estilos ou marcação de classes. Você não teria um <div class = “my-goat -black -white”>. A cabra é ou branca ou preta! A menos que a cabra seja preta e branca, então você realmente deveria ter uma classe <div class = “my-goat -black-and-white”>. Seja esperto quando fizer as suas classes.

Usar !important é ruim.

Nem sempre. A palavra chave !important ao mesmo tempo em que deve ser usada raramente é útil para declarações semanticamente importantes, e ainda mais importante para a acessibilidade do usuário (mas não vamos entrar nisso neste momento). Se você tem uma classe geral .is-hidden, então as chances são de que você quer que qualquer coisa que tenha essa classe fique escondida, não importa o quê. Assim, mesmo se ela tem especificidade de 0 1 0, se a declaração é visibility: hidden !important, podemos ter a certeza de que o nosso .goat.-black.is-hidden será escondido, não importa o que aconteça.

Eu estou sempre lutando com a especificidade.

Por quê? Seus seletores são absurdamente longos ou complicados? Você vê coisas como ul > li span.link > a:hover em toda a sua folha de estilo? Aqui vai uma regra de ouro: seja somente específico onde você deve ser, e seja semântico. Podemos facilmente simplificar que aquele seletor maluco seja algo como .item-link:hover. Isso é o minimamente específico que precisamos ser.

Para mais inspiração na simplificação de seus seletores, imagine alguém lhe dizendo onde é a casa dele. Se ele disse algo como “É 1,4 milhas abaixo da rua de duas faixas chamada rua qualquer coisa, que tem uma luz vermelha e, em seguida, a terceira casa à esquerda com persianas marrons e um gramado verde e uma caixa de correio”, você provavelmente irá perguntar por que ele apenas não te passa um endereço. Seja o mais simples possível.

Então, e se especificidade não existisse?

Bem, então você basicamente estaria escrevendo alguma linguagem imperativa/procedural em que a ordem das coisas importa, e você tem o código que é muito mais difícil de pensar a respeito por que:

  1. Não é modular…
  2. Não é facilmente reutilizável, e…
  3. É muito menos flexível, porque as questões de ordem importam.

Então, por favor, fique feliz que existe especificidade. Ela serve a um propósito muito bom em nossa linguagem de estilo simples declarativa que alguns de nós amamos odiar, e alguns de nós somos estranhos o suficiente para amar, CSS.

Esta é uma resposta a este artigo.

***

David Khourshid faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link http://codepen.io/davidkpiano/post/the-simplicity-of-specificity