Como posso evitar a herança de CSS?

96

Eu tenho um menu de navegação hierárquico em minha barra lateral que usa listas aninhadas (tags <ul> e <li>). Estou usando um tema predefinido que já tem estilos para itens de lista, mas quero alterar o estilo para os itens de nível superior, mas NÃO o aplico aos subitens. Existe uma maneira fácil de aplicar estilos à tag de item de lista de nível superior SEM ter esses estilos em cascata para seus itens de lista filhos? Eu entendo que posso adicionar explicitamente estilos de substituição aos subitens, mas eu realmente gostaria de evitar ter que duplicar todo o código de estilo se houver uma maneira fácil de apenas dizer "aplique esses estilos a esta classe e NÃO faça cascata até quaisquer elementos filhos ". Aqui está o html que estou usando:

<ul id="sidebar">
  <li class="top-level-nav">
    <span>HEADING 1</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
  <li class="top-level-nav">
    <span>HEADING 2</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
</ul>

Portanto, o CSS tem estilos para #sidebar ule #sidebar ul lijá, mas eu gostaria de adicionar estilos adicionais para #sidebar .top-level-navque NÃO sejam cascateados para seus sub-filhos. Existe alguma maneira de fazer isso de forma simples ou preciso reorganizar todos os estilos para que os estilos que estavam #sidebar ulativados agora sejam específicos para certas classes?

Saeed Hassanvand
fonte
2
Eu pesquisei no site por questões semelhantes e não encontrei nada (não dizendo que não havia nenhuma, mas eu procurei). Se você souber o que é, poderia me indicar? Obrigado!
1
stackoverflow.com/questions/747308/breaking-css-inheritance | basicamente diz o que Matthew respondeu.
JasonV
1
Portanto, suponho que a resposta seja "não, não há como fazer isso simplesmente - você tem que substituir manualmente cada configuração de estilo no subitem" - estou interpretando isso corretamente? Obrigado novamente.

Respostas:

38

No momento, não há seletores pais (ou como Shaun Inman os chama, seletores qualificados ), então você terá que aplicar estilos aos itens da lista filho para substituir os estilos nos itens da lista pai.

O cascateamento é o ponto principal das folhas de estilo em cascata, daí o nome.

Scott
fonte
14
Esta informação está desatualizada desde o IE8. Veja a resposta de Silviu Postavaru. Considere mudar a verificação para a resposta mais apropriada.
tmuecksch
lol, concordo em cascata é meio que a essência. Mas deve haver uma maneira de interromper a propagação de um pai específico que pretende ser diferente.
Obay Abd-Algader
73

Você pode usar o seletor filho

Então usando

#parent > child

Fará com que apenas os filhos do primeiro nível tenham os estilos aplicados. Infelizmente, o IE6 não suporta o seletor filho.

Caso contrário, você pode usar

#parent child child

Para definir outros estilos específicos para crianças que estão mais de um nível abaixo.

Silviu Postavaru
fonte
1
Você poderia me mostrar isso em ação no JSFiddle? Tentei centralizar uma div exibida em bloco embutido, mas ainda centraliza o texto dentro da div.
Calmarius de
43

Existe uma propriedade chamada allno módulo de herança CSS3 . Funciona assim:

#sidebar ul li {
  all: initial;
}

A partir de 2016-12, todos os navegadores, exceto IE / Edge e Opera Mini, oferecem suporte a essa propriedade.

Boldewyn
fonte
4
@AndriusDobrotinas será apoiado eventualmente? Parece que não entendi completamente seu comentário. Há um plugin PostCSS que fornece esse recurso, se você usar PostCSS: github.com/maximkoretskiy/postcss-initial
Boldewyn
1
@AndriusDobrotinas, Seu comentário não é construtivo. A resposta foi postada para o bem da comunidade; tente ao máximo ver seus benefícios.
Cody
2
A partir de agora, apenas o IE e o Opera Mini não suportam, todos os outros navegadores principais sim
Legends
@Boldewyn não há valor 'padrão', pelo que se pode dizer a partir do documento w3 vinculado ...
benomatis
@webeno havia, quando escrevi a resposta: w3.org/TR/2013/WD-css3-cascade-20130103/#all-shorthand Parece que existem algumas diferenças sutis entre o antigo defaulte o novo unset, mas agora eu ' não tenho tempo para investigar mais. Sinta-se à vontade para editar a resposta para atualizá-la.
Boldewyn,
26

Você pode usar o seletor * para mudar os estilos filho de volta ao padrão

exemplo

#parent {
    white-space: pre-wrap;
}

#parent * {
    white-space: initial;
}
obrigado
fonte
1
Essa é uma solução muito bonita - especialmente se você não conhece a classe dos pais.
BurninLeo
Acho que sei a resposta para isso, mas há alguma maneira de definir isso embutido? <div id="parent" style="white-space:pre-wrap;*white-space:initial;"/>
1,21 gigawatts de
11

O empacotamento com iframe torna o CSS pai obsoleto.

Tuğrul
fonte
2
Engraçado que esta é a pior resposta feita porque tecnicamente é a única maneira física de parar a herança CSS. Não que eu esteja argumentando que você deva usá-lo dessa forma.
davidelrizzo
2
Eu sugiro não ficar fisicamente com CSS, deixe-o no mundo virtual a que pertence!
michaelward82 de
Na verdade, adicionar iframetornou meu componente filho invisível. Pensamentos?
Kevin Ghaboosi
5

A resposta curta é: Não, não é possível prevenir a herança CSS. Você só pode substituir os estilos definidos nos pais. Veja as especificações:

Cada elemento em um documento HTML herdará todas as propriedades herdáveis ​​de seu pai, exceto o elemento raiz ( html), que não tem um pai. - W3C

Além de substituir todas as propriedades herdadas. Você também pode usar initialpalavras-chave, por exemplo color: initial;. Também pode ser usado junto com all, por exemplo all: initial;, que redefinirá todas as propriedades de uma vez. Exemplo:

.container {
  color: blue;
  font-style: italic;
}
.initial {
  all: initial;
}
<div class="container">
  The quick brown <span class="initial">fox</span> jumps over the lazy dog
</div>

Tabelas de suporte de navegador de acordo com Posso usar ...

  • all (Atualmente sem suporte no IE e Edge, outros são bons)
  • initial (Atualmente sem suporte no IE, outros são bons)

Você pode achar útil usando o seletor direto de filhos> em alguns casos. Exemplo:

.list > li {
  border: 1px solid red;
  color: blue;
}
<ul class="list">
  <li>
    <span>HEADING 1</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
  <li>
    <span>HEADING 2</span>
    <ul>
      <li>sub-heading A</li>
      <li>sub-heading B</li>
    </ul>
  </li>
</ul>

O estilo da borda foi aplicado apenas aos filhos diretos <li>, pois borderé uma propriedade não herdada. Mas a cor do texto foi aplicada a todos os filhos, pois coloré uma propriedade herdada.

Portanto, o >seletor só seria útil com propriedades não herdadas, quando se trata de evitar herança.

Adesivos
fonte
2

Você poderia usar algo como jQuery para "desabilitar" esse comportamento, embora eu dificilmente ache que é uma boa solução, já que você obtém a lógica de exibição em css e javascript. Ainda assim, dependendo dos seus requisitos, você pode descobrir que os utilitários css do jQuery tornam a vida mais fácil para você do que tentar css hacky, especialmente se você estiver tentando fazê-lo funcionar para o IE6

Neil Richards
fonte
2

Por exemplo, se você tiver dois div no documento XHTML.

<div id='div1'>
    <p>hello, how are you?</p>
    <div id='div2'>
        <p>I am fine, thank you.</p>
    </div>
</div>

Em seguida, tente isso em CSS.

#div1 > #div2 > p{
    color: red;
}

afetam apenas o parágrafo 'div2'.

#div1 > p {
    color: red;
} 

afetam apenas o parágrafo 'div1'.

user2848911
fonte
2

Você não precisa da referência de classe para o lis. Em vez de ter CSS como

li.top-level-nav { color:black; }

você pode escrever

ul#sidebar > li { color:black; }

Isso aplicará o estilo apenas aos lis que descem imediatamente da barra lateral ul.

Stevenvh
fonte
0

basta configurá-los de volta para seus padrões no seletor "#sidebar ul li"

Matthew Vines
fonte
Obrigado pela resposta. Sim, eu entendo que posso colocá-los de volta no estilo do subitem, mas estou tentando evitar isso porque estou usando um tema que não criei e me pergunto se posso economizar muito tempo usando apenas alguma regra "do-not-cascade: true" ou algo parecido, em vez de localizar todos os estilos diferentes para os ul's e li's que estão espalhados por todo o lugar e depois se preocupar com consequências indesejadas em outras áreas do site .