Entendendo a precedência de estilo em CSS: Especificidade, Herança e Efeito Cascata

Tradução livre do excelente texto de Steven Bradley, confira aqui o texto original.

Você já enfrentou a situação em que se está tentando aplicar um estilo css a um elemento, mas não funciona? Sua página parece ignorar seu CSS, mas você não descobre o porquê? Talvez você encontre a si mesmo usando !important ou adicionando estilo inline como último recurso. Há uma boa chance do problema que você enfrentou ser precedência em CSS.

Uma melhor compreensão de quais estilos de CSS têm precedência pode levar a menos frustração, código mais limpo e mais organizado, então vamos olhar para três coisas que controlam qual regra CSS se aplica a um dado elemento HTML:

  • Cálculo de especificidade;
  • Herança;
  • O efeito cascata;

Aprender estas regras levará você um a nível superior em desenvolvimento CSS.

Cálculo de Especificidade:

Imagine que seu HTML contém um parágrafo com a classe “bio” aplicado a ele. Você também tem estas duas regras:

p {
font-size: 12px;
}
p.bio {
font-size: 14px;
}

Você provavelmente vai achar que neste caso será 14px. A segunda linha de CSS (p.bio) é mais específica que a primeira quando ela começa com um parágrafo classe “bio”. Contudo, às vezes, especificidade não tão fácil quanto se vê.

Por exemplo, confira o seguinte HTML e CSS:

<!-- HTML -->
<div id="sidebar">
<p class="bio">text here</p>
</div>
/* CSS */
div p.bio {
font-size: 14px;
}
#sidebar p {
font-size: 12px;
}

A primeira linha do CSS, a primeira vista, parece ser mais específica, mas não é. Na realidade, a segunda linha que indicará o font-size do seu parágrafo. Mas, por que disto?

A resposta para essa pergunta necessita a considerar certas regras de especificidade.

Especificidade é calculada contando-se vários componentes do seu CSS e a expressão deles em uma forma (a, b, c, d). Isto será mais claro com um exemplo, mas, primeiro os componentes:

  • Elemento, pseudo elemento: d = 1 — (0, 0, 0, 1)
  • Classe, pseudo classe, atributo: c = 1 — (0, 0, 1, 0)
  • Id: b = 1 — (0, 1, 0, 0)
  • Estilo inline: a = 1 — (1, 0, 0, 0)

O id é mais específico que uma classe que, por sua vez, é mais específica que um elemento.

Você calcula especificidade contando cada uma das opções acima e adicionando 1 a cada a, b, c, ou d. É importante notar que 0, 0, 1, 0 é mais específico que 0, 0, 0, 15. Vejamos alguns exemplos para tornar o cálculo mais claro:

  • p: 1 elemento — (0, 0, 0, 1)
  • div: 1 elemento — (0, 0, 0, 1)
  • #sidebar: 1 id — (0, 1, 0, 0)
  • div#sidebar: 1 elemento, 1 id — (0, 1, 0, 1)
  • div#sidebar p: 2 elementos, 1 id — (0, 1, 0, 2)
  • div#sidebar p.bio: 2 elementos, 1 classe, 1 id — (0, 1, 1, 2)

Vamos olhar novamente aos exemplos acima:

div p.bio {
font-size: 14px; - (0, 0, 1, 2)
}
#sidebar p {
font-size: 12px; - (0, 1, 0, 1)
}

O segundo tem mais especifidade que o primeiro e assim tem precedência.

Um último ponto antes de seguirmos. Importância supera especificidade. Quando colocamos uma propriedade CSS com !important você está substituindo regras de especificidade e assim:

div p.bio {
font-size: 14px; !important
}
#sidebar p {
font-size: 12px;
}

A primeira linha do CSS acima tem precedência ao invés da segunda. !important ainda é principalmente um hack em torno das regras básicas e é algo que você nunca deve precisar se você entender como as regras funcionam.

Herança

A ideia por trás da herança é relativamente fácil de se compreender. Elementos herdam estilos dos seus contêineres pai. Se você definir que a tag body use a cor vermelha, então todo os textos dentro dos elementos de body também serão vermelhos, caso não haja alguma regra específica.

Entretanto, nem toda propriedade CSS é herdada. Por exemplo, margins e paddings são propriedades não herdadas. Se você definir uma margin ou padding para uma div, os parágrafos dentro dela não herdarão a margin e padding definidos na div. Ao invés disso, o parágrafo irá usar o valor padrão definido pelo browser.

Você pode explicitamente definir que uma propriedade será herdada de seu componente pai. Por exemplo, você pode declarar:

p {
margin: inherit;
padding: inherit;
}

E seu parágrafo então irá herdar ambas as propriedades do contêiner pai.

Efeito cascata

No nível mais alto, o efeito cascata é que controla toda a precedência em CSS e funciona da seguinte forma:

  1. Encontre todas as declarações que aplicam a um elemento e propriedade em questão.
  2. Ordene por origem e peso. Origem se refere à fonte da declaração (estilo do autor, estilo do usuário, padrão do browser) e peso se refere à importância da declaração. (Autor tem mais peso que o usuário que tem mais peso que o valor padrão. !important tem mais peso que declarações normais.
  3. Calcule a especificidade.
  4. Se duas regras são iguais em todos os passos acima, a última declaração vence. CSS embutido no HTML sempre vem depois de folhas de estilo externas, independentemente da ordem em que elas estão no arquivo HTML..

A regra 3 é interessante que você preste mais atenção. A 2 serve apenas para você compreender como certas propriedade sobrepõem as outras e como a que são !important sobrepõem a todas.

Também compreenda que seus estilos irão sobrepor os estilos padrão do browser, mas estes existem e geralmente são os que levam a problemas de compatibilidade entre browsers. Usar um arquivo de reset como o do Erick Meyer ou do Yahoo ajuda com estes padrões de estilos.

Resumo

Espero que o texto acima possa ter esclarecido sobre a precedência em CSS. Muitas vezes, se há um conflito de estilos o problema será relacionado a especificidade. Às vezes, quando você tem uma declaração CSS, mas o elemento não se comporta como o esperado, provavelmente é porque ele herda alguma propriedade de um elemento pai ou o valor padrão do browser.

Uma regra geral para quando você declarar seu CSS é usar seletores com a menor especificidade possível. Use #sidebar ao invés de div#sidebar, por exemplo. Admito que quebro esta regra mais do que deveria, mas ao usar a seletores menos específicos se torna mais fácil sobrepô-los quando necessário.

Se você colocar muitas especificidades em seus seletores desde o início, isso pode resolver o seu problema agora. Porém, mais tarde, você terá que aplicar estilos inline ou inserir mais HTML para conseguir a especificidade que você deseja, ou, até mesmo, usando !important. Comece com a menor especifidade e adicione estilos conforme necessário.


Bem pessoal, este foi mais um texto traduzido. Agradeço imensamente ao Brendo Marinho™ pela ajuda na revisão do texto. Espero que este possa ajudá-lo em algumas situações consideradas tristes quando o assunto é CSS. Até a próxima!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.