Hierarquia no CSS ~ O que é? Como funciona? Qual a prioridade?

BHCSS_000.jpg

Este artigo vem um pouco no seguimento de um outro sobre os Selectores no CSS porque foi quando estava a escrever esse artigo que comecei a pensar neste tema da hierarquia no CSS.
Bem... a infopédia diz-nos o seguinte sobre a hierarquia:

nome feminino

  1. distribuição ordenada de poderes civis, militares ou eclesiásticos
  2. classificação ordenada, dentro de qualquer grupo ou corporação, geralmente de acordo com o poder, autoridade ou função
  3. relação de serviço em que o superior tem o poder de direção, e o subalterno o dever de obediência
  4. classificação por ordem crescente ou decrescente; escala

hierarquia eclesiástica
o conjunto das pessoas que na Igreja detêm o poder de ordem ou de jurisdição, subordinadas umas às outras, sob a chefia suprema do papa

Etimologia: Do grego hierarkhía, «dignidade de grão-sacerdote»

infopédia

Numa página dum website ou blogue, a parte que diz aos navegadores como todos os elementos se vão apresentar ao leitor é o CSS.
E num blogue temos esse CSS presente no HTML de três (3) maneiras:

  1. CSS Externo:
    Os estilos estão num ficheiro .css alojado num outro site e são incluídos no teu blogue através duma tag link.
    Exemplo:
    <link href="url-dos-estilos-do-blogue.css" rel="stylesheet" />
           
    Por regra, este link é colocado no HTML logo abaixo de <head>, mas no caso do Blogger algumas vezes poderá estar incluído também em algumas mini-aplicações.
  2. CSS Interno:
    No Blogger, os estilos CSS são escritos numa tag <b:skin>, que é uma tag única e exclusiva do Blogger e que está dentro da tag head.
    Existem duas tags deste tipo que servem o mesmo propósito mas com fins diferentes:
    <b:skin>, onde se escreve os estilos que afectam todo o blogue na parte visível ao visitante,
    <b:template-skin>, onde se escreve os estilos que afectam o painel de controlo, visível somente para os donos do blogue.
    Exemplo:
    <b:skin> /*ESTILOS CSS DO BLOGUE */
      <![CDATA[
      .elemento {
        color: #fff;
      }
      ]]>
    </b:skin>
    <b:template-skin> /*ESTILOS CSS DO PAINEL DO BLOGUE */
      <![CDATA[
      .elemento {
        margin: 3px 5px;
      }
      ]]>
    </b:template-skin>
           
    Também podemos colocar os estilos CSS em tags <style> dentro do próprio artigo/página utilizando a opção Vista de HTML, afectando apenas aquele artigo/página.
    Exemplo:
    <style>
      .elemento {
        font-family: sans-serif;
      }
    </style>
           
    Podemos também utilizar as tags <style> no próprio código HTML do blogue, ou até dentro de mini-aplicações HTML/Javascript.
    Mas ATENÇÃO que qualquer estilo CSS presente na página ou artigo do blogue, esteja onde estiver, vai afectar todo e qualquer elemento a que esteja dirigido dentro da mesma.
  3. CSS Inline:
    Os estilos são aplicados directamente num elemento HTML utilizando o atributo style.
    Exemplo:
    <p style="color: #0b4;">Este paragrafo vai estar escrito a verde</p>
           

    Este parágrafo vai estar escrito a verde

Agora que já estabelecemos COMO o CSS pode estar presente num blogue, vamos ver a ordem em que os navegadores vão "ler" esses estilos no HTML.
E primeiro uma coisa a ter em atenção, o navegador "" de cima para baixo.

Por isso, quando existem múltiplos estilos atribuidos ao mesmo elemento poderá haver conflitos que pode originar situações anómalas e esse elemento não se apresentar como desejamos ao leitor.
Então a ordem de leitura destes estilos, quando em simultâneo no HTML, é a mesma em que apresentei acima.

Tal como o significado da sigla CSS (Cascading Style Sheets ou Folhas de Estilo em Cascata), estes estilos funcionam em cascata com a ordem acima descrita, sendo que a última regra da cascata é a que tem prioridade.
A ordem de prioridade é a seguinte:

  1. CSS Inline
  2. CSS Interno
  3. CSS Externo

Quer isto dizer que em caso de regras iguais com valores diferentes numa mesma página do blogue, o CSS Inline sobrepõe-se ao CSS Interno e este ao CSS Externo.
Outra coisa importante é que mesmo quando existem duas declarações iguais no mesmo CSS, a última regra da lista das declarações é a que prevalece.
E como mencionei antes, é também importante a posição dos diferentes CSS na <head> do HTML, a última folha CSS na ordem descendente do HTML é a que será representada em caso de conflito.

Agora dento dos próprios estilos, a hierarquia CSS determina qual o estilo que será aplicado quando há regras conflitantes, seguindo uma determinada ordem.
Essa ordem será do mais prioritário para o menos prioritário, e é a seguinte:

  1. !important:
    Elementos com declarações com !important têm a maior prioridade e sobrepõem-se a todas as outras.
    Exemplo:
      .elemento {
        color: red !important;
      }
           
    Quando existem conflitos entre várias declarações com !important, predomina a posição na ordem decrescente no HTML.
  2. Estilos Inline:
    Os estilo definidos inline, ou seja, no próprio elemento, dentro do atributo style.
    Exemplo:
    <h1 style="font-size: 22px;">O texto aqui tem um tamanho de 22px.</h1>
           
  3. Selectores de ID (#id):
    Elementos que usam uma #id, que deverá ser única e exclusiva, são mais específicos que classes e tipos, por isso têm maior prioridade.

    DEMONSTRAÇÃO:

              
    <div id="exemplo">
    Viva o <b>Sporting!</b>
    </div>
     
    #exemplo {
      margin: 15px;
    }
    #exemplo b {
      color: #8f8;
      font-size: 22px;
    }
     
    Resultado
    Viva o Sporting!
  4. Classes, atributos e pseudo-classes (.class, [type="text"], :hover):
    Têm menos prioridade do que os selectores de #id, mas maior que os selectores de tipo.
  5. Elementos e pseudo-elementos (div, h1, ::before, ::after):
    Esses selectores têm a menor prioridade e são aplicados apenas se não houver um estilo mais específico que os substitua.

Depois da prioridade pela Importância, temos a prioridade pela Especificidade, que é medida baseado em quão específico é um selector, ou seja, quantos elementos ele pode combinar/atingir.
Existe uma pontuação entre os vários tipos de selector que é usada para especificar a especificidade do mesmo, e que vai determinar qual o estilo a ser aplicado quando há conflito entre as regras.

A pontuação para o cálculo da especificidade é representada por quatro números conforme a importância dos selectores na seguinte ordem: #id, .class, selectores de elementos e selectores universais.
Para fazer esse cálculo, essa pontuação funciona da seguinte maneira:

  • Elemento:
    Um selector de elemento, por exemplo p, div, ou span, tem uma menor especificidade e uma menor pontuação.
    No cálculo da especificidade é representado como 0,0,0,1.
  • Class:
    Um selector de class, por exemplo .minhaclasse, tem uma especificidade maior do que um selector de elemento e é representado como 0,0,1,0.
    Se repararem, agora temos o 1 na segunda posição.
  • ID:
    Um selector de ID, por exemplo #meuID, tem praticamente a maior especificidade e é representado como 0,1,0,0.
    Como podes ver, o 1 passou pra terceira posição.
  • Inline:
    Estilos escritos directamente num elemento HTML utilizandoo atributo style, tem a maior especificidade e é representado como 1,0,0,0.
    E agora o 1 passou pra a principal posição.

Talvez a seguinte tabela ajude a perceber melhor...

Tabela da Especificidade no CSS
Inline ID Classe Elemento Especificidade
<p style ...> 1 0 0 0 1000
h1, h2 0 0 2 2
h1.classe 0 0 1 1 11
#UmaID 0 1 0 0 100
#UmaID h2 0 1 0 1 101
#UmaID #outraID p 0 2 0 1 201
h1 p 0 0 0 2 2
.outraclasse 0 0 1 0 10

Quando existe um conflito nas declarações, é utilizada a especificidade.
A cada selector é atribuído um valor, o número mais alto é usado para determinar o resultado final a apresentar ao visitante.

Caso tenhas curiosidade, podes saber mais em Specificity (existe uma versão em português deste artigo, mas preferi linkar a original porque essa contém todos os elementos necessários para uma melhor compreensão do assunto), ou em Pontuação, Hierarquia e Sequência dos Seletores CSS.
Resumindo o assunto duma forma mais simples de perceber: quanto mais específico for um selector, maior será a sua prioridade, mas vamos a um exemplo prático:

DEMONSTRAÇÃO:

          
<div id="exemplopratico">
  <p class="exemplodeclasse">Texto dentro duma class, que está dentro duma ID <span>com mais este texto dentro dum elemento simples (<b>span</b>) sem qualquer atributo</span>, e também <i style="color:red">um pequeno texto dentro doutro elemento que deverá ser em itálico com cor vermelha</i>.</p>
  <p class="exemplodeclasse2">Texto dentro duma segunda class, que deveria ser branco tal como na irmã mas que é verde porque na declaração da cor tem <b>!important</b>, anulando a declaração da <b>#exemplopratico</b>.</p>
</div> 
 
#exemplopratico p {
  margin: 2px;
  padding: 3px 5px;
  color: white; /* cor branco */
}
#exemplopratico p:before {
  content: "Texto inserido utilizando o pseudo-elemento before";
  margin: 0 3px;
}
.exemplodeclasse i {
  color: skyblue;  /* cor azul claro */
}  
.exemplodeclasse {
  color: blue; /* cor azul */
}
div p {
  color: grey; /* cor cinzento */
}
p {
  color: orange;  /* cor laranja */
}
.exemplodeclasse2 {
  color: lime!important;  /* cor verde */
}
 
Resultado

Texto dentro duma class, que está dentro duma ID com mais este texto dentro dum elemento simples (span) sem qualquer atributo, e também um pequeno texto dentro doutro elemento que deverá ser em itálico com cor vermelha.

Texto dentro duma segunda class, que deveria ser branco tal como na irmã mas que é verde porque na declaração da cor tem !important, anulando a declaração da #exemplopratico.

Então no exemplo acima temos uma div com ID (#exemplopratico), que contém um parágrafo (p) com um pseudo-elemento (:before), contendo uma span simples e um elemento (i) com o estilo CSS dentro do atributo style.
Em comum, a declaração que diz qual a cor a apresentar no texto.

Como podem ver no pseudo-elemento (:before), a cor é branca como resto do texto tal como está estipulada nas declarações de #exemplopratico p e não no elemento "pai", que seria .exemplodeclasse é tem declarado a cor azul.
Isso acontece porque o selector mais específico é #exemplopratico p, não importa a ordem em que os elementos estão declarados.

Se repararem na aba CSS da demonstração, podem verificar que ainda existem outras declarações ignoradas pela mesma razão... excepto a declaração dentro do elemento (i) com o atributo style que é vermelha embora esteja presente junto aos estilos CSS declarando outra cor, o azul-claro.
A última parte do texto na demonstração é verde, apesar de estar dentro dum parágrafo ao lado do outro dentro da div com ID (#exemplopratico) porque na declaração da cor contém !important, o que se sobrepõe aos restantes estilos.

Para terminar, na hierarquia no CSS vem em primeiro lugar a Importância, seguido da prioridade pela Especificidade, e por último, a Ordem em que as regras são declaradas.

Como devem ter reparado, mantive a coisa o mais simples possivel.
Mas caso tenha alguma questão, podes deixar a tua(s) dúvida(s) nos comentários.

E por hoje é tudo. ;)

Até Breve. :-F

Comentários

Malta, comentem, tanto críticas como elogios serão bem-vindos. E eu respondo, não prometo quando mas respondo.

Mas antes de comentarem, leiam as minhas Regras dos Comentários.

Se quiserem deixar o link para o vosso sitio, utilizar alguns estilos ou até inserir videos ou imagens nos comentários DEVEM mesmo ler as indicações nas Regras dos Comentários.

Caso prefiras comentar numa nova janela, ou se o formulário abaixo estiver nos dias ruins, podes clicar aqui.