No desenvolvimento web, é comum que múltiplos estilos CSS tentem influenciar a aparência de um mesmo elemento. Para resolver esses conflitos e determinar qual regra será aplicada, os navegadores seguem um conjunto de princípios conhecidos como prioridade e especificidade. Dominar esses conceitos é fundamental para prever e controlar o comportamento visual das suas páginas.
Hierarquia de Seletores Simples
Quando diferentes tipos de seletores apontam para o mesmo atributo de um elemento, a decisão é tomada com base em uma hierarquia de "força". A ordem de prevalência, do mais potente para o menos potente (antes de considerar !important), é a seguinte:
- Estilos Inline: Definidos diretamente no atributo
stylede um elemento HTML. - Seletores de ID: Referenciam elementos por seu atributo
id(ex:#meuID). - Seletores de Classe, Atributo e Pseudo-classe:
- Classes (ex:
.minhaClasse) - Atributos (ex:
[type="text"]) - Pseudo-clases (ex:
:hover,:first-child)
- Classes (ex:
- Seletores de Elemento e Pseudo-elemento:
- Elementos HTML (ex:
div,p) - Pseudo-elementos (ex:
::before,::after)
- Elementos HTML (ex:
Observe o exemplo abaixo. Mesmo com diversas regras, o estilo definido pelo seletor de ID prevalece sobre os demais:
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exemplo Prioridade Simples</title>
<style>
/* Seletor de ID: Mais específico */
#elementoUnico {
color: darkred;
}
/* Seletor de Classe: Menos específico que ID */
.conteudoDestaque {
color: dodgerblue;
}
/* Pseudo-classe: Especificidade igual à de classe */
/* Supondo que <div id="elementoUnico"> é o primeiro filho do <body> */
body > :first-child {
color: green;
}
/* Seletor de Elemento: Menos específico */
div {
color: gray;
}
</style>
</head>
<body>
<div id="elementoUnico" class="conteudoDestaque">Texto de Exemplo Visual</div>
</body>
</html>
Neste caso, o texto "Texto de Exemplo Visual" será exibido na cor darkred, pois o seletor de ID possui a maior especificidade entre as regras aplicáveis diretamente ao elemento.
Cálculo de Especificidade para Seletores Compostos
Para seletores mais complexos, que combinam vários tipos de seletores, a especificidade é calculada usando um sistema de pontuação. Cada tipo de seletor contribui com um "peso" em três categorias (A, B, C):
- A: Número de seletores de ID.
- B: Número de seletores de classe, seletores de atributo e pseudo-classes.
- C: Número de seletores de elemento (tag) e pseudo-elementos.
A comparação é feita na ordem A → B → C. O seletor com a maior pontuação em A vence. Se as pontuações em A forem iguais, compara-se B. Se B também for igual, compara-se C. Se todas as pontuações (A, B, C) forem idênticas, a regra que foi declarada por último no código CSS (ou mais próxima do elemento no DOM, no caso de inline styles) terá prioridade.
A Regra !important: Esta declaração é uma exceção ao fluxo normal de especificidade, conferindo a prioridade mais alta possível a uma propriedade específica. No entanto, seu uso deve ser moderado, pois pode dificultar a manutenção e a depuração do CSS.
Considere o seguinte exemplo de seletores compostos:
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exemplo Especificidade Composta</title>
<style>
/* Seletor 1: ID e Elemento (1,0,1) */
#blocoPrincipal p {
color: purple;
}
/* Seletor 2: Classe e Elemento (filho direto) (0,1,1) */
.secaoInterna > p {
color: darkorange;
}
/* Seletor 3: Dois Elementos (0,0,2) */
div p {
color: steelblue;
}
/* Seletor 4: Pseudo-classe e Elemento (0,1,1) */
/* Supondo que <p> é o primeiro filho de <div#blocoPrincipal> */
#blocoPrincipal :first-child {
color: forestgreen;
}
/* Seletor 5: Elemento simples (0,0,1) */
p {
color: darkgray;
}
</style>
</head>
<body>
<div id="blocoPrincipal" class="secaoInterna">
<p>Parágrafo Aninhado</p>
</div>
</body>
</html>
Para o texto "Parágrafo Aninhado", os cálculos de especificidade são:
#blocoPrincipal p: (A=1, B=0, C=1).secaoInterna > p: (A=0, B=1, C=1)div p: (A=0, B=0, C=2)#blocoPrincipal :first-child: (A=1, B=1, C=0) -> Este seletor é ainda mais específico para opdentro de#blocoPrincipal. Ele tem A=1 porque usa o ID e B=1 porque usa a pseudo-classe.p: (A=0, B=0, C=1)
Analisando os resultados, #blocoPrincipal :first-child (1,1,0) é o mais específico e fará com que o texto fique forestgreen. Se este não estivesse presente, #blocoPrincipal p (1,0,1) seria o mais específico e a cor seria purple.
O Mito dos Pesos Decimais
É comum encontrar a explicação de que seletores de ID valem 100 pontos, classes 10 e elementos 1, e que a soma desses pontos determina a prioridade. No entanto, essa analogia é enganosa. O sistema de especificidade não é baseado em um cálculo decimal simples onde 11 classes (110 pontos) poderiam superar 1 ID (100 pontos). Na realidade, um ID sempre supera qualquer número de classes. O sistema é mais comparativo: um ID na categoria A sempre será "mais forte" do que qualquer número de seletores na categoria B ou C.
Ordem da Cascata e Fontes de Estilo
A prioridade também é determinada pela origem e pela ordem em que os estilos são declarados. A "cascata" do CSS define a seguinte hierarquia de fontes de estilo:
- Estilos
!importantdo Autor/Usuário: Regras marcadas com!important(porém, um!importantdo usuário pode sobrepor um do autor). - Estilos Inline: Definidos diretamente no HTML.
- Estilos do Autor: Incluem folhas de estilo externas (
<link>) e internas (<style>). Se houver várias, a última declarada prevalece. - Estilos Padrão do Navegador: Estilos que o navegador aplica por padrão (ex: negrito para
<strong>).
Herança de Estilos
Algumas propriedades CSS, como color, font-family e font-size, são naturalmente herdadas por elementos filhos de seus pais. A herança tem a menor prioridade de todas; qualquer estilo explicitamente definido para um elemanto filho sempre substituirá um estilo herdado.
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exemplo Herança</title>
</head>
<body>
<div style="color: darkmagenta;">
<section style="color: teal;">
<p>Este parágrafo herdará a cor azul-petróleo.</p>
</section>
</div>
</body>
</html>
No exemplo acima, o parágrafo herdará a cor teal (azul-petróleo) da <section>, que é seu ancestral direto. O estilo da <div>, embora também seja um ancestral, tem menor prioridade devido à proximidade da <section>.