Aplicar estilos CSS a um elemento, dependendo de seus elementos filhos

203

É possível definir um estilo CSS para um elemento, que será aplicado apenas se o elemento correspondente contiver um elemento específico (como o item filho direto)?

Eu acho que isso é melhor explicado usando um exemplo.

Nota : Estou tentando estilizar o elemento pai , dependendo de quais elementos filho ele contém.

<style>
  /* note this is invalid syntax. I'm using the non-existing
   ":containing" pseudo-class to show what I want to achieve. */
  div:containing div.a { border: solid 3px red; }
  div:containing div.b { border: solid 3px blue; }
</style>

<!-- the following div should have a red border because
     if contains a div with class="a" -->
<div>
  <div class="a"></div>
</div>

<!-- the following div should have a blue border -->
<div>
  <div class="b"></div>
</div>

Nota 2 : Eu sei que posso conseguir isso usando javascript, mas me perguntei se isso seria possível usando alguns recursos CSS desconhecidos (para mim).

M4N
fonte
1
Você pode atualizar a pergunta para indicar, talvez com texto em negrito piscante, que você está tentando estilizar a div PARENT, não seus filhos. Eu sei que as informações estão na própria pergunta, mas, a menos que você queira obter uma tonelada de respostas incorretas, provavelmente vale a pena.
Seth Petry-Johnson
Obrigado @Seth. Tentei melhorar o título e o texto da pergunta. Edite a pergunta se você ainda não está clara.
M4N
3
possível duplicata de Existe um seletor pai CSS?
precisa
Este é o exemplo perfeito de por que esse tipo de suporte no CSS seria ideal: ol < li:nth-child(n+10) { margin-left: 2rem; } ol < li:nth-child(n+100) { margin-left: 3rem; } ol < li:nth-child(n+1000) { margin-left: 4rem; }em um mundo ideal, isso aumentaria a margem do oldependente do número de lifilhos contidos, de modo que a margem à esquerda fosse tão larga quanto precisava ser.
Jonmark Weber

Respostas:

124

Tanto quanto sei, o estilo de um elemento pai com base no elemento filho não é um recurso disponível do CSS. Você provavelmente precisará de scripts para isso.

Seria maravilhoso se você pudesse fazer algo como div[div.a]ou div:containing[div.a]como você disse, mas isso não é possível.

Você pode considerar considerar o jQuery . Seus seletores funcionam muito bem com tipos 'contendo'. Você pode selecionar a div, com base no conteúdo filho e, em seguida, aplicar uma classe CSS ao pai, tudo em uma linha.

Se você usa jQuery, algo nesse sentido pode funcionar (não testado, mas a teoria existe):

$('div:has(div.a)').css('border', '1px solid red');

ou

$('div:has(div.a)').addClass('redBorder');

combinado com uma classe CSS:

.redBorder
{
    border: 1px solid red;
}

Aqui está a documentação para o seletor jQuery "has" .

KP.
fonte
15
Nota lateral: para um melhor desempenho, a página de documentos do jQuery para o :hasseletor aconselha o uso do .has()método ( api.jquery.com/has ) => aplicado à pergunta atual que daria, por exemplo,$('div').has('div.a').css('border', '1px solid red');
Frosty Z
Para que isso funcione, seria preciso usar mutação observador, para verificar wether a criança mudou de estado ...
Legends
Isso realmente não responde à pergunta que é "Existe uma maneira de fazer isso com CSS". Ele afirma claramente: "Eu sei que posso conseguir isso usando javascript, mas apenas me perguntei se isso seria possível usando alguns recursos CSS desconhecidos (para mim)".
precisa saber é o seguinte
developer.mozilla.org/pt-BR/docs/Web/CSS/:tem , acho que esse :hasseletor pode funcionar, mas está na versão de rascunho e nenhum navegador suporta.
AliF50 03/03
62

Basicamente, não. A seguir, seria o que você procurava em teoria:

div.a < div { border: solid 3px red; }

Infelizmente não existe.

Existem algumas descrições na linha de "por que diabos não". Um bem elaborado por Shaun Inman é muito bom:

http://www.shauninman.com/archive/2008/05/05/css_qualified_selectors

Justin Wignall
fonte
34
apenas uma atualização 8 anos depois: ainda não há suporte para esse método seletor.
Kraang Prime
1
Há um rascunho de trabalho para esse recurso na forma de uma :has()pseudo-classe, mas só o usaremos no CSS4. A partir de agora (final de 2019), o JS ainda é a única maneira de obter essa funcionalidade.
Zepp.lee 16/12/19
Acredito que isso não habilite os estilos css, ainda será necessário o javascript para usar o seletor. A menos que isso tenha mudado?
perfil completo de Justin Wignall
3
9 anos e eles acham que esse recurso é desnecessário?
Loi Nguyen Huynh
1

Além da resposta da @ kp:

Estou lidando com isso e, no meu caso, tenho que mostrar um elemento filho e corrigir a altura do objeto pai de acordo (o dimensionamento automático não está funcionando no cabeçalho de bootstrap por algum motivo, não tenho tempo para depurar) .

Mas, em vez de usar o javascript para modificar o pai, acho que vou adicionar dinamicamente uma classe CSS ao pai e mostrar seletivamente o CSS aos filhos de acordo. Isso manterá as decisões na lógica e não com base em um estado CSS.

tl; dr; aplique os estilos ae bao pai <div>, não ao filho (é claro, nem todos serão capazes de fazer isso. Por exemplo, componentes angulares que tomam decisões por conta própria).

<style>
  .parent            { height: 50px; }
  .parent div        { display: none; }
  .with-children     { height: 100px; }
  .with-children div { display: block; }
</style>

<div class="parent">
  <div>child</div>
</div>

<script>
  // to show the children
  $('.parent').addClass('with-children');
</script>
Mauricio Morales
fonte
0

No meu caso, tive que alterar o preenchimento de célula de um elemento que continha uma caixa de seleção de entrada para uma tabela que está sendo renderizada dinamicamente com DataTables:

<td class="dt-center">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

Após implementar o seguinte código de linha na função initComplete, consegui produzir o preenchimento correto, que impedia que as linhas fossem exibidas com uma altura anormalmente grande

 $('tbody td:has(input.a)').css('padding', '0px');

Agora, você pode ver que os estilos corretos estão sendo aplicados ao elemento pai:

<td class=" dt-center" style="padding: 0px;">
    <input class="a" name="constCheck" type="checkbox" checked="">
</td>

Essencialmente, esta resposta é uma extensão da resposta da @ KP, mas quanto mais colaboração for implementada, melhor. Em suma, espero que isso ajude outra pessoa, porque funciona! Por fim, muito obrigado @KP por me levar na direção certa!

milhas
fonte