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?

NGLN
źródło
3
Możliwy duplikat Czy istnieje selektor nadrzędny CSS?
TylerH
Możliwe rozwiązanie: stackoverflow.com/q/39374918/3597276
Michael Benjamin

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.

NGLN
źródło
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 )

facet_m
źródło
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 .

Onur Yıldırım
źródło
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

Kae Verens
źródło
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;
}
Remy Lagerweij
źródło
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

Jan Mellström
źródło
-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>

Sanogoals
źródło
-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

admazzola
źródło
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