Jak stylizować element nadrzędny po najechaniu na element podrzędny?


160

Wiem, że nie istnieje selektor rodzica CSS , ale czy można stylizować element rodzicielski po najechaniu kursorem na element potomny bez takiego selektora?

Oto przykład: rozważ przycisk usuwania, który po najechaniu kursorem podświetli element, który ma zostać usunięty:

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

Jak za pomocą czystego CSS zmienić kolor tła tej sekcji, gdy mysz znajduje się nad przyciskiem?



Odpowiedzi:


134

Cóż, to pytanie zadawane jest już wiele razy, a krótka typowa odpowiedź brzmi: nie można tego zrobić za pomocą czystego CSS. Jest w nazwie: Kaskadowe arkusze stylów obsługują stylizację tylko w kierunku kaskadowym, a nie w górę.

Ale w większości przypadków, w których pożądany jest ten efekt, jak w podanym przykładzie, nadal istnieje możliwość wykorzystania tych kaskadowych charakterystyk, aby osiągnąć pożądany efekt. Rozważ ten pseudo znacznik:

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

Sztuczka polega na tym, aby dać rodzeństwu taki sam rozmiar i pozycję jak rodzic i nadać styl rodzeństwu zamiast rodzica. To będzie wyglądać tak, jakby stylizowany był rodzic!

A teraz, jak wystylizować rodzeństwo?

Kiedy dziecko unosi się w powietrzu, rodzic również, ale rodzeństwo nie. To samo dotyczy rodzeństwa. To kończy się trzema możliwymi ścieżkami selektorów CSS do stylizacji rodzeństwa:

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

Te różne ścieżki dają kilka fajnych możliwości. Na przykład uwolnienie tej sztuczki na przykładzie w pytaniu skutkuje następującymi skrzypcami :

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

Przykładowy obraz nadrzędny stylu

Oczywiście w większości przypadków ta sztuczka polega na zastosowaniu pozycjonowania absolutnego, aby nadać rodzeństwu taki sam rozmiar jak rodzic, a jednocześnie pozwolić dziecku pojawić się w nim.

Czasami konieczne jest użycie bardziej kwalifikowanej ścieżki selektora, aby wybrać określony element, jak pokazano na tym skrzypcach, które implementują tę sztuczkę wiele razy w menu drzewiastym. Całkiem niezłe.


1
To jest dobre do podświetlania, ale nie zadziała, jeśli spróbujesz zmienić kolor czcionki, prawda?
Jahanzeb Khan

1
@JahanzebKhan Zmiana koloru czcionki to żaden problem .
NGLN,

116

Wiem, że to stare pytanie, ale udało mi się to zrobić bez pseudo dziecka (ale pseudo wrapper).

Jeśli ustawisz rodzica na nie pointer-events, a następnie dziecko divz pointer-eventsustawieniem na auto, to działa :)
Zauważ, że <img>tag (na przykład) nie załatwia sprawy.
Należy również pamiętać, aby ustawić pointer-eventssię autodo innych dzieci, które mają swój własny detektor zdarzeń lub inaczej stracą swoją funkcjonalność kliknięcia.

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>

Edycja:
Jak uprzejmie zauważył Shadow Wizard : warto wspomnieć, że to nie będzie działać dla IE10 i starszych. (Stare wersje FF i Chrome, zobacz tutaj )


3
Warto wspomnieć, że to nie zadziała dla IE10 i starszych. (Stare wersje FF i Chrome, zobacz tutaj )
Shadow Wizard is Ear For You

2
Ustawienie wartości none oznacza również, że detektory zdarzeń w tym elemencie nie będą działać ..!
rhazen

1
@rhazen masz całkowitą rację. Chociaż z mojego doświadczenia wynika, że ​​to użycie jest zwykle połączone z jednym obszarem / elementem kliknięcia, więc możesz przypisać odbiornik kliknięcia do rodzica
guy_m.

Co powiesz na to, że mam dwa poziomy, rodzic, dziecko1 i dziecko dziecko1. Dodałem pointer-events none do parent i pointer-events auto do child. Chcę najechać na dziecko1 z wyjątkiem dziecka dziecka 1. Demo tutaj: codepen.io/lion5893/pen/WNQgyVx
Nam Lê Quý

13

Innym, prostszym podejściem (do starego pytania) ...
byłoby umieszczenie elementów jako rodzeństwa i użycie:

Selektor sąsiadującego rodzeństwa ( +) lub Ogólny selektor rodzeństwa ( ~)

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

wprowadź opis obrazu tutaj

Demo Fiddle tutaj .


1
warto zauważyć, że to działa tylko wtedy, gdy #targets pojawia się po #control w DOM (tj. nie możesz wpływać na poprzednie rodzeństwo, tylko śledzenie rodzeństwa)
Gio

10

nie ma selektora CSS do wyboru rodzica wybranego dziecka.

możesz to zrobić za pomocą JavaScript


3
prawdziwe. coś takiego jak $ (child) .hover (function () {$ (this) .closest (parentSelector) .addClass ('hoverClass')}, function () {$ (this) .closest (parentSelector) .removeClass ('hoverClass') )});
Aamir Afridi

8
@AamirAfridi To nie jest jednak czysty JS, musisz do tego użyć jQuery.
Ivotje50

6

Jak wspomniano wcześniej, „nie ma selektora CSS do wyboru rodzica wybranego dziecka”.

Więc albo:


Oto przykład dla JavaScript / jQuery rozwiązanie

Po stronie javascript:

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

A po stronie CSS miałbyś coś takiego:

.is-hover {
  background-color: red;
}

3

To rozwiązanie zależy w pełni od projektu, ale jeśli masz nadrzędny element DIV, na którym chcesz zmienić tło podczas najeżdżania na dziecko, możesz spróbować naśladować rodzica za pomocą ::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: "";
}

Zobacz pełny przykład skrzypiec tutaj


-1

Proste rozwiązanie jquery dla tych, którzy nie potrzebują czystego rozwiązania CSS:

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

W Sass jest to niezwykle łatwe! Nie zagłębiaj się w JavaScript w tym celu. Selektor & w sass robi dokładnie to.

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


6
-1 Sass nie dodaje więcej funkcjonalności do css, po prostu ułatwia pisanie. Wszystko, co możesz zrobić w sass, można zrobić w css i odwrotnie.
Dastur

3
@Dastur Biorąc pod uwagę zmienne i miksy, powiedziałbym, że Sass dodaje bardzo dużo do CSS. Możesz to wszystko zrobić w CSS, w ten sam sposób, w jaki nadal możesz pisać wyrafinowane oprogramowanie, używając zwykłego starego C. Współczesne języki dodają wiele bez włączania czegoś, czego wcześniej nie można było zrobić. To samo z Sass i CSS.
Cobus Kruger

6
@Cobus Kruger Częściowo masz rację, ale nie możesz tego porównać. Podczas gdy języki takie jak c ++ c # i javascript mogą być oparte na C, nie zmieniają się w C przed uruchomieniem. Sass jest konwertowany w css przed uruchomieniem, więc nigdy tak naprawdę nie ładujesz arkusza stylów sass, tylko arkusz CSS.
Dastur
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.