Tableless - Desenvolvimento inteligente com Padrões Web

25/04/2011
CSS

Pontuação de especificidade da CSS

Entenda como o browser calcula a especificidade do seu seletor e evite conflitos entre estilos.

Por


Você pode ler algo sobre herança e especificadade do CSS aqui. O problema é que nesse artigo eu não explico muito sobre a pontuação da especificidade do CSS. Como que o browser calcula qual propriedade é mais especifica que outra?

Para que serve?

A graça do CSS é que você pode manipular os estilos de diversos elementos com pouco esforço. Se você quer modificar a font de todos os parágrafos ou títulos do seu site é simples de se fazer mudando um parâmetro da linha onde é definida a propriedade

1
font

. Se você quiser definir estilos restritos para os botões por exemplo, também é muito simples, basta criar uma classe e pronto. Você tem toda a flexibilidade que precisa para formatar os elementos do layout.

O problema é que uma hora ou outra você cai no problema de herança de estilos, onde alguns elementos herdam estilos de elementos criados para outros propósitos. Isso acontece que você utilizou mesmas tags, ou colocou elementos do mesmo gênero, mas com funções visuais diferentes dentro de um mesmo pai e assim por diante.
Outro problema é quando uma pessoa define um determinado estilo para um elemento P, por exemplo. Depois, com o passar do projeto, outra pessoa tenta formatar um parágrafo em outro determinado ponto do layout, mas não consegue, porque os estilos estão entrando em conflito com um código criado a tempos atrás. Aí entra o trabalho de investigação para descobrir em qual ponto está o código que causa o conflito de propriedades. E isso acontece porque um seletor mais específico que o seu foi criado, e isso sobrescreve seu código.

Seu seletor pode ser algo parecido:

.content p {color:red;}

E colocam um seletor mais específico, assim:

.content article p {color:blue;}

Logo, um problema de conflito pode acontecer. E acredite, isso é mais comum do que você pensa, principalmente em projetos onde várias pessoas escrevem client-side.

Cálculo de especificidade

Como o browser define o grau de prioriedades dos seletores? É simples: ele pontua o seletor de acordo com sua estrutura. Cada elemento, classe, id e etc vale pontos de especificidade. A pontuação é somada numa estrutura simples que começam com zeros (0), assim: 0,0,0,0. A estrutura é composta por quatro números, quanto mais o número estiver na esquerda, mais específico e mais força ele tem sobre outros seletores. Veja a tabela a baixo:

Seletor Pontuação Descrição
div ul li a 0,0,0,4 4 elementos, 4 pontos na primeira casa
div.content ul li 0,0,1,3 Uma classe vale um ponto na segunda casa. Mais 3 elementos, mais 3 pontos na primeira casa.
a:hover 0,0,1,1 Um elemento, um ponto na primeira casa. Mais uma pseudo-classe, que equivale a uma classe e logo ganha um ponto na segunda casa.
div.menu a:hover 0,0,2,2 Dois elementos, dois pontos na primeira casa. Mais uma classe e uma pseudo-classe, mais dois pontos na segunda casa.
#content p 0,1,0,1 Um ID equivale a um ponto na terceira casa. Mais um elemento, que equivale a um ponto na primeira casa.
article#content p 0,1,0,2 Dois elementos, dois pontos na primeira casa. Um ID, um ponto na terceira casa.

Simples, ahn?!

Agora vamos entender melhor. Veja o seletor abaixo:

header nav ul li a {color:blue;}

Como tem 5 elementos descritos, a pontuação é 0,0,0,5.
Se colocarmos uma classe nos links e escrevermos assim:

.itemlink {color:red;}

Cada classe equivale a uma pontua na segunda casa, ficando assim: 0,0,1,0. Quanto mais para esquerda, mais prioriedade o seletor tem. Logo, o nosso seletor acima, que tem um ponto na segunda casa por causa da classe (0,0,1,0) é mais específico que o primeiro seletor que escrevemos, que tem 5 ítens (0,0,0,5) e sobrescreverá o estilo. Se colocarmos um ID, como no exemplo abaixo:

#menu a {color:yellow;}

A prioridade fica 0,1,0,1. Um elemento, um ponto na primeira casa, um ID um ponto na terceira casa. Tendo ID, a prioridade aumenta mais ainda que a classe, e este seletor sobrescreverá todos os outros que fizemos.

A Quarta Casa

Nos exemplos acima vimos até a terceira casa. A quarta casa é utilizada em duas ocasiões: 1) quando colocamos CSS inline, ou seja, diretamente no elemento HTML e quando temos o valor

1
!important

declarado no valor do código CSS. Logo:

#menu a {color:yellow;}

O código acima tem pontuação 0,1,0,0. E perde para o código abaixo:

Home

Colocando o STYLE diretamente no elemento temos uma pontuação de 1,0,0,0. Não importa se outros seletores tem ID, CLASS e etc… Ele sempre vai sobrepor porque é pontuado na última casa.

A mesma coisa acontece quando utilizamos o !important. Segue o código:

#menu a {color:yellow !important;}

Tem a mesma pontuação do atributo STYLE: 1,0,0,0.

E quando há a mesma pontuação?

Suponhamos que dois seletores tenham a mesma pontuação, como abaixo:

.menu a {color:yellow;}
.optItem a {color:blue;}

Pontuação: 0,0,1,1. Um elemento, uma classe. O desempate nesse caso é: quem veio por último ganha.
No nosso exemplo acima o browser leu que os links dentro do elemento CLASS MENU fiquem com cor AMARELO. Logo depois ele leu que estes mesmos links ficassem com cor AZUL, então essa linha sobrescreveu a anterior.

Recomendações

É interessante que você resolva os problemas de conflito utilizando o próprio seletor, sem apelar para o

1
!important

ou o atributo

1
style

. Assim você mantém o código sob controle. Se começarmos a colocar muito

1
!important

no meio do código, equivale a regra de: se todo o mundo é importante, ninguém é importante. E então o

1
!important

perde seu efeito e passará a ser inútil.

Por Diego Eis

Diego Eis criou o Tableless para disseminar os padrões web no Brasil. Como consultor já treinou equipes de empresas como Nokia, Globo.com, Yahoo! e iG. É palestrante e empreendedor.

http://twitter.com/diegoeis/

Veja os outros posts de

  • http://www.construsitebrasil.com Márcio

    Ajudou bastante, belo post. Esclareceu algumas duvidas para a criação de sites.

  • http://caueamaral.com Cauê Amaral

    Bom artigo Diego, muito interessante a forma como foi mostrada a especificidade dos seletores CSS, parabéns.

  • http://www.gdesignweb.com.br Luis Gustavo

    Boa jovem Diego,

    mais um dia, ou melhor, uma noite de conhecimento, janto seus artigos todo dia cara. Obrigado por compartilhar!

    Abraço!

  • http://twitter.com/oieduardorabelo Eduardo Rabelo

    Sensacional o artigo Diego!

    Me perguntei a mesma coisa esses dias, como é caracterizado cada casa pelo browser…

    Simples e objetivo,

    Parabéns!

  • Marcos

    Parabéns Diego, muito importante este seu post.
    Creio que muita gente não conhecia estas regras, contando comigo.

    Abraço.

  • http://luizz.com.br Luizz

    Bom , mas será que especificar muito pode ficar algo exagerado, causando perda desempenho (ou performance) ?

  • http://www.sevenlabs.com.br Ígor

    Muito bom!

    Como o amigo acima perguntou, o importante é conciliar essa forma de pontuação com a questão performance. O fato de haver uma pontuação maior para seletores mais específicos não significa que eles serão exagerados. Por isso pra mim o planejamento antes de começar a codificar e a constante re-fatoração do seu CSS (afim de evitar especificidades e !importants) conseguem derrubar esses problemas.

  • Leandro Santos

    A cada post, um aprendizado diferente, esclarecendo muito a questão de .class e #divs quando não são aplicadas no layout, ai é apelar para o !important ou style, com esse post tudo pode ser resolvido com uma analise na estrutura do CSS sem precisar apelar para metedos não convencionais.

  • Leandro Santos

    @Luizz, Acho que não, com estrutura css especificada, seu código fica mais otimizado, pois com as especificações você não precisar escrever mais linhas para obter o mesmo resultado.

  • estenio

    Bom, eu particularmente não uso !important e na minha opinião o css que tem esta mal feito, quanto a especifidade ja tive muito problema com isso quando comecei a trabalhar com css mas descobri(pelo menos pra mim) que a melhor arma para não cair em tantas heranças é o planejamento. Digo isso por que se vc planejar tudo o que vai ser comum no site todo dificilmente haverá problemas com herança. Separar o site em várias partes dentro do css é uma ótima pedida pois, fazendo isto é como se eu criasse minis css dentro da folha de estilo assim me dando agilidade tanto na produção quanto na manutenção minha ou de terceiros.

  • Carlos Eduardo

    Ótimo artigo, já tinha lido algo sobre isso em livros, mas a maneira com que você explicou facilitou bastante. Parabéns e obrigado =D

  • Jean Cesar

    Era uma dúvida que eu tinha. Ficou tudo muito claro agora, vou poder escrever ainda melhor estilos mais limpos e perfeitos.

    Valeu cara =D

  • Dorian

    Muito bem explicado diego.No começo,eu li sobre isso mas não entendi muito bem.Mas agora,na hora que der um problema de herança no meu código eu ja vou saber como ajeitar =DD Obrigado cara !

  • http://www.mestresascensos.com Mestres Ascensos

    Os códigos deste site tem me ajudado.

    Muito obrigado.

  • http://johnwendel.com.br John

    Show de bola esse artigo :)

  • Pingback: Especificidade das CSS « da[two]k's Blog =)

  • http://brunno.net Brunno Gomes

    Muito bom o artigo, ficou mais simples de entender os conflitos agora.

    Agora essa questão do desempenho é uma boa, qual a relação especificidade x desempenho?