Jak wpływać na inne elementy po najechaniu jednym z nich

459

To, co chcę zrobić, to divto, że gdy jakiś zostanie ukryty, wpłynie to na właściwości innego div.

Na przykład, w tej wersji demonstracyjnej JSFiddle , kiedy najedziesz myszką na #cubeto, zmienia się, background-colorale to, czego chcę, to to, że kiedy najedziesz myszką#container , #cubema to wpływ.

div {
  outline: 1px solid red;
}
#container {
  width: 200px;
  height: 30px;
}
#cube {
  width: 30px;
  height: 100%;
  background-color: red;
}
#cube:hover {
  width: 30px;
  height: 100%;
  background-color: blue;
}
<div id="container">

  <div id="cube">
  </div>

</div>

Trufa
źródło

Odpowiedzi:

984

Jeśli sześcian znajduje się bezpośrednio w pojemniku:

#container:hover > #cube { background-color: yellow; }

Jeśli sześcian znajduje się obok (po zamknięciu kontenera znacznika) kontenera:

#container:hover + #cube { background-color: yellow; }

Jeśli sześcian jest gdzieś w pojemniku:

#container:hover #cube { background-color: yellow; }

Jeśli sześcian jest rodzeństwem kontenera:

#container:hover ~ #cube { background-color: yellow; }
Mikrofon
źródło
106
Nie zapomnij o ogólnym kombinatorze rodzeństwa ~dla „kostki jest gdzieś po kontenerze w DOM i dzieli rodzica”
robertc
3
To fajnie. Czy jest jakieś źródło, w którym mogę znaleźć więcej informacji na ten temat? Czy jest obsługiwany przez wszystkie przeglądarki, czy jest to CSS3? Byłoby wspaniale mieć więcej informacji na ten temat. Dzięki wielkie!
Anonimowy
2
+1 Świetna odpowiedź @Mike. Co jeśli #containerjest obok #cube, tzn. #containerNastępuje #cube?
PeterKA
4
Co zrobić, jeśli ukryty element znajduje się w pojemniku (że chcemy, aby to nastąpiło) ??? Na przykład: #cube: hover #container {Some CSS Effects}
Hanzallah Afgan
2
Dobra odpowiedź !! Co, jeśli chcę zmienić rodzica, gdy unosię dziecko? Myślę, że nie ma na to selektora.
Mikel
41

W tym konkretnym przykładzie możesz użyć:

#container:hover #cube {
    background-color: yellow;   
}

Ten przykład działa tylko, ponieważ cubejest dzieckiem container. W przypadku bardziej skomplikowanych scenariuszy należy użyć innego CSS lub JavaScript.

Emmett
źródło
35

Korzystanie z selektora rodzeństwa jest ogólnym rozwiązaniem do stylizowania innych elementów po najechaniu myszką na dany element, ale działa tylko wtedy, gdy pozostałe elementy są zgodne z danym elementem w DOM . Co możemy zrobić, gdy pozostałe elementy powinny znajdować się przed ukrytym? Powiedzmy, że chcemy zaimplementować widget oceniania paska sygnału, taki jak ten poniżej:

Widżet oceniania paska sygnału

Można to faktycznie zrobić łatwo za pomocą modelu CSS Flexbox, ustawiając flex-directionnareverse , aby elementy były wyświetlane w odwrotnej kolejności niż w DOM. Powyższy zrzut ekranu pochodzi z takiego widgetu, zaimplementowanego w czystym CSS.

Flexbox jest bardzo dobrze obsługiwany przez 95% nowoczesnych przeglądarek.

Dan Dascalescu
źródło
Czy można to zmienić, aby podświetlenie nie zniknęło po przesunięciu myszy z jednego paska na drugi? Błysk jest trochę rozpraszający.
Cerbrus,
@Cerbrus: Dodano rozwiązanie, które nie ukrywa aktywowania wskaźnika myszy, gdy mysz znajduje się między pasami. Minusem jest to, że szerokość prętów nie jest już równa.
Dan Dascalescu
1
Spróbuj tego w swoim pierwszym fragmencie: wł. .rating div, Usuń margines i dodajborder-right: 4px solid white;
Cerbrus
1
Kierunek wygięcia (niezbyt obsługiwany dla IE) LUB 1) domyślnie czarny 2) cały niebieski na myszy nad pojemnikiem 3) czarny dla następnego rodzeństwa na pasku po najechaniu myszą :)
Stephane Mathis
Zrobiłem to skrzypce, które (przynajmniej dla mnie) sprawiło, że stało się trochę bardziej widoczne na temat tego, co się tutaj dzieje. jsfiddle.net/maxshuty/cj55y33p/3
maxshuty
8

Ogromne podziękowania dla Mike'a i Robertca za ich pomocne posty!

Jeśli masz dwa elementy w swoim HTML i chcesz :hover zmienić jeden z nich i zmienić styl na drugi, oba elementy muszą być bezpośrednio powiązane - rodzice, dzieci lub rodzeństwo. Oznacza to, że dwa elementy muszą znajdować się jeden w drugim lub oba muszą znajdować się w tym samym większym elemencie.

Chciałem wyświetlać definicje w polu po prawej stronie przeglądarki, gdy moi użytkownicy czytają moją witrynę i :hoverwyróżniają terminy; dlatego nie chciałem, aby element „definicja” był wyświetlany w elemencie „tekst”.

Prawie się poddałem i po prostu dodałem javascript do mojej strony, ale to jest przyszłość! Nie powinniśmy znosić tylnego sassa z CSS i HTML, który mówi nam, gdzie musimy umieścić nasze elementy, aby osiągnąć pożądane efekty! W końcu poszliśmy na kompromis.

Podczas gdy rzeczywiste elementy HTML w pliku muszą być zagnieżdżone lub zawarte w jednym elemencie, aby były :hoverdla siebie ważnymi celami, cssposition atrybutu można używać do wyświetlania dowolnego elementu w dowolnym miejscu. Użyłem position: fixed, aby umieścić cel mojej :hoverakcji tam, gdzie chciałem, na ekranie użytkownika, niezależnie od jego lokalizacji w dokumencie HTML.

HTML:

<div id="explainBox" class="explainBox"> /*Common parent*/

  <a class="defP" id="light" href="http://en.wikipedia.or/wiki/Light">Light                            /*highlighted term in text*/
  </a> is as ubiquitous as it is mysterious. /*plain text*/

  <div id="definitions"> /*Container for :hover-displayed definitions*/
    <p class="def" id="light"> /*example definition entry*/ Light:
      <br/>Short Answer: The type of energy you see
    </p>
  </div>

</div>

CSS:

/*read: "when user hovers over #light somewhere inside #explainBox
    set display to inline-block for #light directly inside of #definitions.*/

#explainBox #light:hover~#definitions>#light {
  display: inline-block;
}

.def {
  display: none;
}

#definitions {
  background-color: black;
  position: fixed;
  /*position attribute*/
  top: 5em;
  /*position attribute*/
  right: 2em;
  /*position attribute*/
  width: 20em;
  height: 30em;
  border: 1px solid orange;
  border-radius: 12px;
  padding: 10px;
}

W tym przykładzie cel :hoverpolecenia z elementu wewnątrz #explainBoxmusi być #explainBoxalbo w środku#explainBox . Atrybuty pozycji przypisane do #definicji zmuszają go do pojawienia się w żądanej lokalizacji (na zewnątrz #explainBox), nawet jeśli technicznie znajduje się w niepożądanej pozycji w dokumencie HTML.

Rozumiem, że używanie tego samego #iddo więcej niż jednego elementu HTML jest uważane za złą formę ; jednakże w tym przypadku przypadki #lightmożna opisać niezależnie ze względu na ich odpowiednie pozycje w unikatowych #idelementach. Czy istnieje powód, aby id #lightw tym przypadku nie powtarzać ?

stóg
źródło
Dość długa odpowiedź na tak krótki punkt, ale oto jsfiddle tego jsfiddle.net/ubershmekel/bWgq6/1
ubershmekel
1
niektórzy browersi wystraszą się, gdy użyjesz tego samego IDwiele razy. Po prostu użyj class.
Serj Sagan
6

Tylko to działało dla mnie:

#container:hover .cube { background-color: yellow; }

Gdzie .cubejest CssClass z#cube .

Testowane w Firefox , Chrome i Edge .

CyberHawk
źródło
4

Oto kolejny pomysł, który pozwala wpływać na inne elementy bez rozważania żadnego konkretnego selektora i tylko przy użyciu :hover stanu głównego elementu.

W tym celu polegam na użyciu właściwości niestandardowych (zmiennych CSS). Jak możemy przeczytać w specyfikacji :

Właściwości niestandardowe są właściwościami zwykłymi , dlatego można je zadeklarować w dowolnym elemencie, są rozwiązywane przy użyciu normalnych reguł dziedziczenia i kaskady ...

Chodzi o to, aby zdefiniować niestandardowe właściwości w głównym elemencie i używać ich do stylizowania elementów potomnych, a ponieważ te właściwości są dziedziczone, wystarczy je zmienić w głównym elemencie po najechaniu myszą.

Oto przykład:

#container {
  width: 200px;
  height: 30px;
  border: 1px solid var(--c);
  --c:red;
}
#container:hover {
  --c:blue;
}
#container > div {
  width: 30px;
  height: 100%;
  background-color: var(--c);
}
<div id="container">
  <div>
  </div>
</div>

Dlaczego może to być lepsze niż używanie określonego selektora w połączeniu z aktywowaniem?

Mogę podać co najmniej 2 powody, które sprawiają, że ta metoda jest dobra do rozważenia:

  1. Jeśli mamy wiele zagnieżdżonych elementów, które mają te same style, pozwoli to uniknąć złożonego selektora, aby celować nimi wszystkimi po najechaniu myszą. Korzystając z właściwości niestandardowych, po prostu zmieniamy wartość po najechaniu kursorem na element nadrzędny.
  2. Własności niestandardowej można użyć do zastąpienia wartości dowolnej właściwości, a także jej częściowej wartości. Na przykład możemy zdefiniować właściwość niestandardową dla koloru i używamy go w border, linear-gradient, background-color, box-shadowitd. To pozwoli uniknąć nam resetowanie wszystkich tych właściwości przy aktywowaniu.

Oto bardziej złożony przykład:

.container {
  --c:red;
  width:400px;
  display:flex;
  border:1px solid var(--c);
  justify-content:space-between;
  padding:5px;
  background:linear-gradient(var(--c),var(--c)) 0 50%/100% 3px no-repeat;
}
.box {
  width:30%;
  background:var(--c);
  box-shadow:0px 0px 5px var(--c);
  position:relative;
}
.box:before {
  content:"A";
  display:block;
  width:15px;
  margin:0 auto;
  height:100%;
  color:var(--c);
  background:#fff;
}

/*Hover*/
.container:hover {
  --c:blue;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
</div>

Jak widzimy powyżej, potrzebujemy tylko jednej deklaracji CSS , aby zmienić wiele właściwości różnych elementów.

Temani Afif
źródło