Como estilizar o elemento pai ao passar o mouse sobre um elemento filho?

160

Eu sei que não existe um seletor pai CSS , mas é possível estilizar um elemento parental ao passar o mouse sobre um elemento filho sem esse seletor?

Para dar um exemplo: considere um botão de exclusão que, quando pairado, destacará o elemento que está prestes a ser excluído:

<div>
    <p>Lorem ipsum ...</p>
    <button>Delete</button>
</div>

Por meio de CSS puro, como alterar a cor de fundo desta seção quando o mouse está sobre o botão?

NGLN
fonte
3
Possível duplicata de Existe um seletor pai CSS?
TylerH
Possível solução: stackoverflow.com/q/39374918/3597276
Michael Benjamin

Respostas:

134

Bem, essa pergunta é feita muitas vezes antes, e a resposta curta e típica é: Ela não pode ser feita por CSS puro. Está no nome: as folhas de estilo em cascata suportam apenas o estilo na direção em cascata, e não para cima.

Mas na maioria das circunstâncias em que esse efeito é desejado, como no exemplo dado, ainda há a possibilidade de usar essas características em cascata para alcançar o efeito desejado. Considere esta pseudo marcação:

<parent>
    <sibling></sibling>
    <child></child>
</parent>

O truque é dar ao irmão o mesmo tamanho e posição do pai e estilizar o irmão em vez do pai. Parece que o pai está estilizado!

Agora, como estilizar o irmão?

Quando a criança passa o mouse, o pai também, mas o irmão não. O mesmo vale para o irmão. Isso termina em três caminhos possíveis do seletor de CSS para estilizar o irmão:

parent sibling { }
parent sibling:hover { }
parent:hover sibling { }

Esses caminhos diferentes permitem algumas boas possibilidades. Por exemplo, desencadear esse truque no exemplo da pergunta resulta nesse violino :

div {position: relative}
div:hover {background: salmon}
div p:hover {background: white}
div p {padding-bottom: 26px}
div button {position: absolute; bottom: 0}

Exemplo de imagem pai de estilo

Obviamente, na maioria dos casos, esse truque depende do uso de posicionamento absoluto para dar ao irmão o mesmo tamanho do pai e ainda deixar a criança aparecer dentro do pai.

Às vezes, é necessário usar um caminho de seletor mais qualificado para selecionar um elemento específico, como mostrado neste violino que implementa o truque várias vezes em um menu em árvore. Muito bom mesmo.

NGLN
fonte
1
Isso é bom para destacar, mas não funcionará se você tentar alterar a cor da fonte, estou certo?
9139 Jahanzeb Khan
1
@JahanzebKhan Alterar a cor da fonte não é problema .
NGLN
117

Eu sei que é uma pergunta antiga, mas consegui fazê-lo sem um pseudo filho (mas um pseudo wrapper).

Se você definir o pai como não pointer-events, e um filho divcom o pointer-eventsconjunto auto, ele funcionará :)
Observe que a <img>tag (por exemplo) não funciona.
Lembre-se também para definir pointer-eventsa autode outras crianças que têm o seu próprio ouvinte de evento, ou caso contrário, eles vão perder a sua funcionalidade clique.

div.parent {  
    pointer-events: none;
}

div.child {
    pointer-events: auto;
}

div.parent:hover {
    background: yellow;
}    
<div class="parent">
  parent - you can hover over here and it won't trigger
  <div class="child">hover over the child instead!</div>
</div>

Edit:
Como o Shadow Wizard observou gentilmente: vale a pena mencionar que isso não funcionará no IE10 e abaixo. (Versões antigas do FF e Chrome também, veja aqui )

guy_m
fonte
3
Vale ressaltar que isso não funcionará para o IE10 e abaixo. (Versões antigas do FF e Chrome também, veja aqui )
Assistente de Sombra é ouvido para Você
2
Definir eventos do ponteiro como nenhum também significa que os ouvintes de eventos nesse elemento não funcionarão ..!
precisa saber é o seguinte
1
@ rhazen você está absolutamente certo. Embora, pela minha experiência, esse uso esteja geralmente conectado a uma única área / elemento de clique, para que você possa atribuir o ouvinte de clique ao pai
guy_m
Que tal se eu tiver dois níveis, pai, filho1 e filho de filho1. Adicionei eventos-ponteiro nenhum ao pai e eventos-ponteiro automaticamente ao filho. Quero passar para child1, exceto o filho da child 1. Demonstração aqui: codepen.io/lion5893/pen/WNQgyVx
Nam Lê Quý
13

Outra abordagem mais simples (para uma pergunta antiga) ..
seria colocar elementos como irmãos e usar:

Seletor de irmão adjacente ( +) ou Seletor de irmão geral ( ~)

<div id="parent">
  <!-- control should come before the target... think "cascading" ! -->
  <button id="control">Hover Me!</button>
  <div id="target">I'm hovered too!</div>
</div>
#parent {
  position: relative;
  height: 100px;
}

/* Move button control to bottom. */
#control {
  position: absolute;
  bottom: 0;
}

#control:hover ~ #target {
  background: red;
}

insira a descrição da imagem aqui

Demonstração Fiddle aqui .

Onur Yıldırım
fonte
1
importante notar que este só funciona isso #targets vem depois # Controle no DOM (ou seja, você não pode afetar os irmãos anteriores, apenas seguintes irmãos)
Gio
10

não há seletor de CSS para selecionar um pai de um filho selecionado.

você poderia fazer isso com JavaScript

Kae Verens
fonte
3
verdade. algo como $ (child) .hover (function () {$ (this) .closest (parentSelector) .addClass ('hoverClass')}, function () {$ (this) .closest (parentSelector) .removeClass ('hoverClass' )});
Aamir Afridi
8
@AamirAfridi Isso não é JS puro, é preciso usar o jQuery com isso.
Ivotje50
6

Como mencionado anteriormente "não há seletor de CSS para selecionar um pai de um filho selecionado".

Então você:


Aqui está o exemplo da solução javascript / jQuery

No lado do javascript:

$('#my-id-selector-00').on('mouseover', function(){
  $(this).parent().addClass('is-hover');
}).on('mouseout', function(){
  $(this).parent().removeClass('is-hover');
})

E no lado CSS, você teria algo parecido com isto:

.is-hover {
  background-color: red;
}
Remy Lagerweij
fonte
3

Essa solução depende totalmente do design, mas se você tiver uma div pai que deseja alterar o plano de fundo ao passar o mouse em um filho, tente imitar o pai com um ::after/ ::before.

<div class="item">
    design <span class="icon-cross">x</span>
</div>

CSS:

.item {
    background: blue;
    border-radius: 10px;
    position: relative;
    z-index: 1;
}
.item span.icon-cross:hover::after {
    background: DodgerBlue;
    border-radius: 10px;
    display: block;
    position: absolute;
    z-index: -1;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    content: "";
}

Veja um exemplo completo aqui

Jan Mellström
fonte
-1

Uma solução simples de jquery para quem não precisa de uma solução css pura:

    $(".letter").hover(function() {
      $(this).closest("#word").toggleClass("hovered")
    });
.hovered {
  background-color: lightblue;
}

.letter {
  margin: 20px;
  background: lightgray;
}

.letter:hover {
  background: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="word">
  <div class="letter">T</div>
  <div class="letter">E</div>
  <div class="letter">S</div>
  <div class="letter">T</div>
</div>

Sanogoals
fonte
-8

Isso é extremamente fácil de fazer em Sass! Não mergulhe no JavaScript para isso. O seletor & no sass faz exatamente isso.

http://thesassway.com/intermediate/referencing-parent-selectors-using-ampersand

admazzola
fonte
6
-1 O Sass não adiciona mais funcionalidade ao css, apenas facilita a escrita. Tudo o que você pode fazer no sass pode ser feito em css e vice-versa.
Dastur
3
@ Dastur Dadas variáveis ​​e mixins, eu diria que o Sass adiciona muito ao CSS. Você pode fazer tudo isso em CSS, da mesma maneira que ainda poderia escrever software sofisticado usando C. velho e simples. As linguagens modernas acrescentam muito sem permitir algo que não podia ser feito antes. Mesmo com Sass e CSS.
Cobus Kruger
6
@Cobus Kruger Seu parcialmente certo, mas você não pode fazer essa comparação. Enquanto linguagens como c ++ c # e javascript podem ser baseadas em C, elas não se transformam em C antes do tempo de execução. O Sass é convertido em CSS antes do tempo de execução, portanto, você nunca carrega verdadeiramente uma folha de estilo Sass, apenas uma CSS.
Dastur