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?


3
Possível duplicata de Existe um seletor pai CSS?
— TylerH

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.


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 )


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 .


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


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;
}

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


-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>


-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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.