Comment styliser l'élément parent lors du survol d'un élément enfant?

160

Je sais qu'il n'existe pas de sélecteur parent CSS , mais est-il possible de styliser un élément parental lors du survol d'un élément enfant sans un tel sélecteur?

Pour donner un exemple: considérez un bouton de suppression qui, lorsqu'il est survolé, mettra en évidence l'élément qui est sur le point d'être supprimé:

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

Au moyen de CSS pur, comment changer la couleur de fond de cette section lorsque la souris est sur le bouton?

NGLN
la source
3
Possible duplication de Y a
TylerH
Solution possible: stackoverflow.com/q/39374918/3597276
Michael Benjamin

Réponses:

134

Eh bien, cette question est posée plusieurs fois auparavant, et la réponse courte typique est: cela ne peut pas être fait par du CSS pur. C'est dans le nom: les feuilles de style en cascade ne prennent en charge que le style en cascade, pas vers le haut.

Mais dans la plupart des cas où cet effet est souhaité, comme dans l'exemple donné, il est toujours possible d'utiliser ces caractéristiques en cascade pour atteindre l'effet souhaité. Considérez ce pseudo balisage:

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

L'astuce consiste à donner au frère la même taille et à la même position que le parent et à styliser le frère au lieu du parent. Cela ressemblera au style du parent!

Maintenant, comment coiffer le frère?

Lorsque l'enfant est survolé, le parent l'est aussi, mais le frère ne l'est pas. Il en va de même pour le frère ou la sœur. Cela se termine par trois chemins de sélecteur CSS possibles pour styliser le frère:

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

Ces différents chemins offrent de belles possibilités. Par exemple, déchaîner cette astuce sur l'exemple de la question aboutit à ce violon :

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

Exemple d'image parente de style

Évidemment, dans la plupart des cas, cette astuce dépend de l'utilisation du positionnement absolu pour donner au frère la même taille que le parent, et laisser toujours l'enfant apparaître dans le parent.

Parfois, il est nécessaire d'utiliser un chemin de sélecteur plus qualifié pour sélectionner un élément spécifique, comme le montre ce violon qui implémente l'astuce plusieurs fois dans un menu arborescent. Très bien vraiment.

NGLN
la source
1
C'est bon pour mettre en évidence, mais ne fonctionnera pas si vous essayez de changer la couleur de la police, n'est-ce pas?
Jahanzeb Khan
1
@JahanzebKhan Changer la couleur de la police ne pose aucun problème .
NGLN
117

Je sais que c'est une vieille question, mais j'ai juste réussi à le faire sans pseudo enfant (mais un pseudo wrapper).

Si vous définissez le parent avec no pointer-events, puis un enfant divavec pointer-eventsdéfini sur auto, cela fonctionne :)
Notez que la <img>balise (par exemple) ne fait pas l'affaire.
Pensez également à définir pointer-eventssur autopour les autres enfants qui ont leur propre écouteur d'événements, sinon ils perdront leur fonctionnalité de clic.

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:
Comme Shadow Wizard l'a gentiment noté: il vaut la peine de mentionner que cela ne fonctionnera pas pour IE10 et les versions antérieures. (Anciennes versions de FF et Chrome aussi, voir ici )

guy_m
la source
3
Il convient de mentionner que cela ne fonctionnera pas pour IE10 et les versions antérieures. (Anciennes versions de FF et Chrome aussi, voir ici )
Shadow Wizard est Ear For You
2
Définir les événements de pointeur sur aucun signifie également que les écouteurs d'événements sur cet élément ne fonctionneront pas ..!
rhazen le
1
@rhazen vous avez absolument raison. Bien que d'après mon expérience, cette utilisation soit généralement connectée à une seule zone / élément de clic, vous pouvez donc affecter l'écouteur de clic au parent
guy_m
Que diriez-vous si j'ai deux niveaux, parent, enfant1 et enfant de child1. J'ai ajouté des événements de pointeur aucun au parent et des événements de pointeur automatiques à l'enfant. Je veux passer la souris sur enfant1 sauf l'enfant de l'enfant 1. Démo ici: codepen.io/lion5893/pen/WNQgyVx
Nam Lê Quý
13

Une autre approche plus simple (à une vieille question) ...
consisterait à placer les éléments comme frères et sœurs et à utiliser:

Sélecteur de frères et sœurs adjacents ( +) ou sélecteur général de frères et sœurs ( ~)

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

entrez la description de l'image ici

Démo Fiddle ici .

Onur Yıldırım
la source
1
il convient de noter que cela ne fonctionne que #targets vient après #control dans le DOM (c'est-à-dire que vous ne pouvez pas affecter les frères et sœurs précédents, uniquement les frères et sœurs suivants)
Gio
10

il n'y a pas de sélecteur CSS pour sélectionner un parent d'un enfant sélectionné.

vous pouvez le faire avec JavaScript

Kae Verens
la source
3
vrai. quelque chose comme $ (child) .hover (function () {$ (this) .closest (parentSelector) .addClass ('hoverClass')}, function () {$ (this) .closest (parentSelector) .removeClass ('hoverClass') )});
Aamir Afridi
8
@AamirAfridi Ce n'est pas du pur JS cependant, vous devez utiliser jQuery avec ça.
Ivotje50
6

Comme mentionné précédemment, "il n'y a pas de sélecteur CSS pour sélectionner un parent d'un enfant sélectionné".

Donc vous non plus:


Voici l'exemple pour le javascript / jQuery solution

Du côté javascript:

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

Et du côté CSS, vous auriez quelque chose comme ça:

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

Cette solution dépend entièrement de la conception, mais si vous avez un div parent dont vous souhaitez modifier l'arrière-plan lorsque vous survolez un enfant, vous pouvez essayer d'imiter le parent avec un ::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: "";
}

Voir un exemple complet de violon ici

Jan Mellström
la source
-1

Une solution jquery simple pour ceux qui n'ont pas besoin d'une solution css pure:

    $(".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
la source
-8

C'est extrêmement facile à faire à Sass! Ne vous lancez pas dans JavaScript pour cela. Le sélecteur & dans sass fait exactement cela.

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

admazzola
la source
6
-1 Sass n'ajoute pas plus de fonctionnalités au css, il facilite simplement l'écriture. Tout ce que vous pouvez faire dans sass peut être fait en css et vice versa.
Dastur
3
@Dastur Compte tenu des variables et des mixins, je dirais que Sass ajoute énormément au CSS. Vous pouvez tout faire en CSS, de la même manière que vous pourriez toujours écrire des logiciels sophistiqués en utilisant le vieux C. Les langues modernes ajoutent beaucoup sans activer quelque chose qui ne pouvait pas être fait auparavant. Idem avec Sass et CSS.
Cobus Kruger
6
@Cobus Kruger Vous avez partiellement raison, mais vous ne pouvez pas faire cette comparaison. Alors que les langages comme c ++ c # et javascript peuvent être basés sur C, ils ne se transforment pas en C avant l'exécution. Sass est converti en css avant l'exécution, donc vous ne chargez jamais vraiment une feuille de style sass, juste une feuille de style css.
Dastur