Tableless - Desenvolvimento inteligente com Padrões Web

21/07/2009
CSS

Efeito cascata, herança e especificidade do CSS

O efeito cascata do CSS é controlado pela especificidade e pela herança das propriedades.

Por


Herança

Existem algumas propriedades do CSS que quando aplicadas aos “elementos pais”, os “elementos filhos” herdam a característica aplicada no pai. Um exemplo disso é a propriedade color. Quando aplicamos a propriedade color em um elemento div, o texto dos elementos contidos no div são coloridos de acordo com a propriedade.

1
2
3
div {
   color: green;
}

O texto que há dentro deste div irá ter a cor verde, independente se este texto está “solto” dentro do div ou se ele está dentro de um parágrafo, por exemplo. Ou seja, os filhos herdaram o resultado desta propriedade. A mesma coisa acontece para, por exemplo, a propriedade font-size.

Há também as propriedades não herdadas pelos “filhos”. Estas propriedades geralmente são propriedades referentes a formatação da caixa, como por exemplo a propriedade width, height, margin, padding e assim por diante.

Essa herança é responsável por uma parte da cascata. É aí que está uma das primeiras vantanges de se utilizar o CSS no desenvolvimento com padrões. A vantagem da herança é exatamente podermos modificar poucas linhas do CSS para fazer alterações no site inteiro, sem ter que caçar elemento por elemento e modificando suas propriedades.

A herança é largamente utilizada em frameworks de CSS ou até mesmo em técnicas para que a customização de layouts seja explorada de forma automática ou manual pelo cliente, como homes de portais, e-commerce etc. Assim, o controle fica mais genérico, e é aí que entra a especificidade do CSS para controlar o detalhe.

O valor INHERIT

O valor inherit é utilizada em propriedades destinadas aos elementos filhos. Suponha que você tem um elemento div. Este elemento div tem uma borda e você quer que seus filhos tenham a mesma borda. Veja o código:

1
2
3
4
<div id="pai">
  <div>um filho</div>
  <div>outro filho</div>
</div>

No CSS, o normal seria fazer isso:

1
2
3
4
5
6
7
div#pai {
  border: 2px solid black;
}

div#pai div {
  border: 2px solid black;
}

Se você quisesse modificar a borda do pai e mesmo assim manter a borda do filho, teria que fazer das alterações no código. O valor inherit serve para que o filho sempre herde um determinado valor de uma determinada propriedade do pai. Quando o valor do pai muda, o valor do filho também. Veja o código e o exemplo.

1
2
3
4
5
6
7
div#pai {
  border: 2px solid black;
}

div#pai div {
  border: inherit;
}

Especificidade

A especificidade define os detalhes. Quando você define no body as propriedades font-family, font-size, essas propriedades são herdadas por toda árvore de elementos do documento. Isso tráz uma uniformidade para o texto, mas nem todos os elementos terão esse valor genérico de font, logo você terá que ser mais específico e definir valores diferentes de font para estes elementos. É aí que a mágica acontece.

Suponha que você tenha o seguinte código:

1
2
3
4
5
6
7
8
<div class="content">
   <p>
        Vivamus in leo lacus. <em>Nam condimentum viverra odio</em>, non molestie orci commodo sit amet. <strong><em>Proin aliquet leo eu</em></strong> ipsum adipiscing tristique vestibulum nunc gravida. In porta dignissim enim sit amet vulputate. Quisque lacinia malesuada convallis. Sed sit amet orci non lacus sollicitudin pellentesque.
   </p>
</div>
   <p>
        Vivamus in leo lacus. <em>Nam condimentum viverra odio</em>, non molestie orci commodo sit amet. <strong><em>Proin aliquet leo eu</em></strong> ipsum adipiscing tristique vestibulum nunc gravida. In porta dignissim enim sit amet vulputate. Quisque lacinia malesuada convallis. Sed sit amet orci non lacus sollicitudin pellentesque.
   </p>

E também o código CSS:

1
2
3
em {
   background: red;
}

Definimos no código acima que os elementos em terão o background vermelho. Isso irá capturar os 4 elementos em que colocamos no HTML. Correto? Ótimo. Estamos sendo bem genéricos aqui. Ele irá capturar todos os elementos em, não importa onde ele esteja. Vamos analisar outro código CSS:

1
2
3
4
5
6
7
em {
   background: red;
}

div p em {
   background: green;
}

Já mudamos toda a história com este seletor. Queremos dizer que apenas os em que estão dentro de p e que por sua vez estão dentro de um div terão o background verde. Deixamos a regra mais específica excluindo todos os elementos em que estão fora do div. Os em que estão fora do div continuam com o background vermelho.

No caso acima, a ordem não altera o resultado da renderização. O seletor mais específico sempre é o que vai funcionar.

Essa explicação é bem básica. Contudo, entendendo como ela funciona, você sabe o que acontece com seletores mais complexos.

O valor !important

A especificidade apresenta muitos problemas quando a equipe é grande e o código CSS está gigante. Você tenta fazer uma alteração em um determinado objeto, e nada funciona. Isso acontece porque alguém já definiu um seletor mais específico que o seu e definiu um valor diferente para sua propriedade, e isso te impede de fazer a alteração que precisa. Essa seria uma cena clássica, mas há outros cenários cujo o uso do valor !important.
O !important indica que aquela propriedade sempre será a principal, e que nunca será substituída mesmo que o seletor seja mais complexo. Veja:

1
2
3
4
5
6
7
p {
   color: black;
}

div p {
   color: red;
}

No código acima, o parágrafo terá a cor vermelha por conta do seletor div p ser mais específico.

1
2
3
4
5
6
7
p {
   color: black !important;
}

div p {
   color: red;
}

Agora, mesmo o seletor div p sendo mais específico, ele não controlará o elemento. O !important está jogando toda a relevancia para o color: black;.
Use com cuidado. Se você colocar muitos !important no seu código, a utilidade deste valor se perderá. Veja o exemplo.

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

  • ZullCore

    Excelente artigo, eu aprendi o valor !important hehehehhe!
    Continue assim! Tá bombando!
    Abraços!

  • http://jaderubini.net Jader Rubini

    O valor “inherit” é realmente muito útil, mas “adivinha-qual-browser” costuma não se dar muito bem com ele. Pelo menos nas vezes que usei, funcionava quando bem entendia.

    Pra contornar isso, eu prefiro usar agrupamento de seletores.

  • http://www.gabrielizaias.com Gabriel Silva

    Hierarquia css é muito importante.

    Curti o artigo, parabéns.

    Pra quem quer saber mais, recomendo o artigo do stuffandnonsense, sobre hierarquia css e star wars: http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

  • http://www.turmadochaves.com Evandro

    Bacana o artigo. Bem conceitual. Parabéns! ;)

    Sobre herança, há quem diga que ela está ligada a desempenho: quanto menos, melhor. Nunca vi um artigo conceitual sobre esse problema. Tá aí um tema que acho interessante num próximo artigo ;)

  • Roberto Almeida Longhi

    Hum …

    Provavelmente não pequei o conceito do important ainda mas, quando tinha problemas de CSS onde precisava sobrescrever uma propriedade eu tornava o seletor dela mais complexo que o que precisava sobrescrever.

    Acho interessante que o !important sobrescreve até o style inline.

    =]
    []‘s

  • Pingback: Aula n.7 – Curso de HTTM, CSS e Javascript em Joinville

  • http://mariosergio.blogspot.com/ Mario Sergio

    Eu tenho medo quando vejo alguma DIV não identificada.

    “Todo filho deve conhecer o nome de seus pais”

    :/

  • http://designcombolachas.blogspot.com/ Thiago Cavalcanti

    A frase mais importante do artigo é a última, sem sombra de dúvida.
    O !important é útil na hora do desespero, mas quando utilizado por preguiça o resultado é um CSS de manutenção tão difícil que muitas vezes vale mais a pena refazê-lo do zero.

  • http://www.seuwebsitenainternet.com.br Eduardo Ferreira

    no momento que se faz um script comentado, fica fácil alterar, o problema é quando tá cheio de DIVs sem comentário, de onde está pegando o CSS!!

    aí vira um inferno!!

  • http://mastodi.wordpress.com Mastodi

    Excelente artigo, agora eu realmente sei diferenciar todas as caracteristicas do CSS. Obrigado

    Meu site: Mastodi Report

  • http://www.juliobitencourt.com/ Julio Cesar Bitencourt

    Show de bola o artigo! Eu não entendia bem a função do valor INHERIT e agora ficou claro.

    Um bom exemplo do uso de !important é para fazer um hack para que nosso “amigo” IE6 interprete a propriedade min-height. Vejam http://www.pinceladasdaweb.com.br/blog/2007/06/04/min-height-altura-minima-para-elementos-de-bloco-com-css/

  • http://www.softov.com.br fernadoSoftov

    muito bom,,,,

  • Pingback: Clica Aqui » Digest 06/09: Técnicas de CSS

  • Pingback: Clica Aqui » nth-child

  • Pingback: Introdução: diversidade dos meios acesso | Boas práticas de Desenvolvimento com Padrões Web

  • http://d3rf.com.br Frederico Fiuza

    O !important acabou de resolveu um problemão meu, vlw !

  • Pingback: Herança, especificidade e efeito cascata na CSS: Como funciona? | Ramon Victor

  • http://www.lucaspeperaio.com.br Lucas Peperaio – WebDesigner

    legal o seu tutorial
    pena que nem tudo funcione no IE…logo logo ela ta saindo do ar (IE 6)

  • http://www.iotecnologia.com.br Nícholas André

    Gostei, não conhecia o !important

    Bom artigo.

    Abraços

  • Gui Premonsa

    @Evandro: Quanto mais objetivo o seletor CSS for, melhor será o desempenho dele na questão do processamento. Ao desenvolver para Mobile, é preciso tomar muito cuidado com isso, pois o mínimo de esforço por parte do celular consome rapidamente sua bateria.

  • Helio Pereira

    Fala Diego! O conceito de herança eu já entendia, só que agora apareceu uma situação onde estou quebrando um pouco a cabeça e não encontro solução em lugar nenhum.

    Tenho um menu em lista com os valores width e height de cada li definidos no css, e dentro de uma dessas li tenho um submenu que também terá uma lista só que sem largura e altura definidas. Porém as li´s desse submenu estão herdando os valores de width e height da lista pai (embora em todo lugar eu leio que essas propriedades não são herdadas).

    Eu preciso que as li´s dessa segunda lista não herde as propriedades da primeira, mas sem precisar definir novos valores, quero que ele cresça de acordo com seu conteúdo. Já tentei usar o value:auto mas não adiantou.

    Alguma alma caridosa teria a solução? Agradeço desde já!

  • http://twitter.com/diegoeis/ Diego Eis

    ul li
    Seria a lista pai.

    Para as li internas não herdarem, o mais básico seria:
    ul li ul li

    Mas claro, com classes e etc… tudo bonitinho.

  • Pingback: Especificidade de Seletores CSS | Tableless - Desenvolvimento com Padrões Web

  • estenio

    Na minha opinião temos o seguinte cenário

    !important = Site mal feito
    inherit = desnecessário em alguns casos, pois se por exemplo se um bloco de codigo tem um pai ao inves de vc fazer assim:

    div#pai { border: 2px solid black;}
    div#pai div { border: inherit; }

    Eu faria assim:

    #pai, #pai div { border: 2px solid black;}

    pois raciocinando que os dois tenham as mesmas propriedades qual seria a necessidade de criar outra linha de css? nenhuma, e se caso em um futuro próximo o código mudar ai sim eu criaria uma linha somente para o filho.

    Alias uma dica minha é usar o css tudo na mesma linha, que no começo é estranho mas vc for organizado com o tempo vc nunca se perderá em seu código

    Um amigo ali em baixo estava perguntando sobre a lista não herdar em caso de sub-menu, claro que nesse caso é como o diego diz coloque classes mas se vc tiver um pouco mais de força de vontade é só vc negar mesmo por que duvido que seu sub-menu não vá ter algo de diferente do pai

  • Pingback: Efeito cascata, herança e especificidade do CSS « K4M1K4Z3 {B.I.}