Come influenzare altri elementi quando un elemento viene spostato


459

Quello che voglio fare è quando un certo divviene sospeso, influenzerebbe le proprietà di un altro div.

Ad esempio, in questa demo di JSFiddle , quando si passa con il mouse su di #cubeesso cambia, background-colorma quello che voglio è che quando si passa con il mouse sopra #container, #cubeè interessato.

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>

Risposte:


986

Se il cubo si trova direttamente all'interno del contenitore:

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

Se il cubo si trova accanto a (dopo la chiusura del contenitore tag) il contenitore:

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

Se il cubo si trova da qualche parte all'interno del contenitore:

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

Se il cubo è un fratello del contenitore:

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

107
Non dimenticare il combinatore generale di pari livello ~per "il cubo è da qualche parte dopo il contenitore nel DOM e condivide un genitore"
robertc,

3
È abbastanza bello. C'è qualche fonte in cui posso trovare maggiori informazioni a riguardo? È supportato da tutti i browser, è CSS3? Sarebbe bello avere qualche informazione in più a riguardo. Grazie mille!
Anonimo

2
+1 Ottima risposta @Mike. Che cosa succede se #containerè accanto #cube, cioè #containersegue #cube?
PeterKA,

4
Cosa fare se l'elemento hovered è all'interno del contenitore (che vogliamo che venga effettuato) ??? Ad esempio: #cube: hover #container {Alcuni effetti CSS}
Hanzallah Afgan

2
Buona risposta !! Che dire se voglio cambiare il genitore quando passo con il mouse sul bambino. Penso che non ci sia selettore per quello.
Mikel

41

In questo esempio particolare, puoi usare:

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

Questo esempio funziona solo poiché cubeè figlio di container. Per scenari più complicati, è necessario utilizzare CSS diversi o JavaScript.


35

L'uso del selettore di pari livello è la soluzione generale per lo styling di altri elementi quando si passa con il mouse su uno specifico, ma funziona solo se gli altri elementi seguono quello indicato nel DOM . Cosa possiamo fare quando gli altri elementi dovrebbero effettivamente essere prima di quello sospeso? Supponiamo di voler implementare un widget di valutazione della barra dei segnali come quello qui sotto:

Widget di valutazione della barra del segnale

Questo può effettivamente essere fatto facilmente usando il modello di flexbox CSS, impostando flex-directionsu reverse, in modo che gli elementi vengano visualizzati nell'ordine opposto a quello in cui si trovano nel DOM. Lo screenshot sopra è da un tale widget, implementato con CSS puro.

Flexbox è molto ben supportato dal 95% dei browser moderni.


Potrebbe essere modificato in modo che l'evidenziazione non scompaia quando si sposta il mouse da una barra all'altra? Il lampeggiamento è un po 'fonte di distrazione.
Cerbrus,

@Cerbrus: aggiunta una soluzione che non nasconde il passaggio del mouse quando il mouse si trova tra le barre. Il rovescio della medaglia è che la larghezza delle barre non è più uguale.
Dan Dascalescu,

1
Prova questo nel tuo primo frammento: on .rating div, rimuovi il margine e aggiungiborder-right: 4px solid white;
Cerbrus

1
Direzione flessibile (non ben supportata per IE) OPPURE 1) nero per impostazione predefinita 2) tutto blu al passaggio del mouse sul contenitore 3) nero per il prossimo fratello al passaggio del mouse :)
Stephane Mathis,

Ho realizzato questo violino che (almeno per me) lo ha reso un po 'più attento a ciò che stava succedendo qui. jsfiddle.net/maxshuty/cj55y33p/3
maxshuty

8

Grazie mille a Mike e Robertc per i loro utili post!

Se hai due elementi nel tuo HTML e desideri :hoversovrascriverne uno e scegliere come target un cambio di stile nell'altro, i due elementi devono essere direttamente correlati: genitori, figli o fratelli. Ciò significa che i due elementi devono essere uno all'interno dell'altro oppure devono essere entrambi contenuti nello stesso elemento più grande.

Volevo visualizzare le definizioni in una casella sul lato destro del browser mentre i miei utenti leggevano il mio sito e i :hovertermini evidenziati; pertanto, non volevo che l'elemento "definizione" fosse visualizzato all'interno dell'elemento "testo".

Ho quasi rinunciato e ho appena aggiunto javascript alla mia pagina, ma questo è il futuro, per favore! Non dovremmo tollerare la retroassistenza di CSS e HTML che ci dice dove dobbiamo posizionare i nostri elementi per ottenere gli effetti che vogliamo! Alla fine abbiamo compromesso.

Mentre gli elementi HTML effettivi nel file devono essere nidificati o contenuti in un singolo elemento per essere validi :hoverobiettivi reciproci, l' positionattributo css può essere utilizzato per visualizzare qualsiasi elemento dove vuoi tu. Ho usato position: fixed per posizionare il bersaglio della mia :hoverazione dove lo volevo sullo schermo dell'utente indipendentemente dalla sua posizione nel documento HTML.

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

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

In questo esempio, la destinazione di un :hovercomando da un elemento all'interno #explainBoxdeve essere #explainBoxo anche all'interno #explainBox. Gli attributi di posizione assegnati a #definitions lo costringono ad apparire nella posizione desiderata (all'esterno #explainBox) anche se tecnicamente si trova in una posizione indesiderata all'interno del documento HTML.

Capisco che è considerato una forma errata utilizzare lo stesso #idper più di un elemento HTML; tuttavia, in questo caso le istanze di #lightpossono essere descritte in modo indipendente a causa delle loro rispettive posizioni in #idelementi univoci. C'è qualche motivo per non ripetere id #lightin questo caso?


Piuttosto la risposta lunga per un punto così breve, ma ecco un jsfiddle di esso jsfiddle.net/ubershmekel/bWgq6/1
ubershmekel

1
alcuni brower impazziranno quando si usano gli stessi IDpiù volte. Basta usare a class.
Serj Sagan,

6

Solo questo ha funzionato per me:

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

Dov'è .cubeCssClass di #cube.

Testato su Firefox , Chrome e Edge .


4

Ecco un'altra idea che ti consente di influenzare altri elementi senza considerare alcun selettore specifico e usando solo lo :hoverstato dell'elemento principale.

Per questo, farò affidamento sull'utilizzo di proprietà personalizzate (variabili CSS). Come possiamo leggere nelle specifiche :

Le proprietà personalizzate sono proprietà ordinarie , quindi possono essere dichiarate su qualsiasi elemento, vengono risolte con le normali regole di eredità e cascata ...

L'idea è quella di definire le proprietà personalizzate all'interno dell'elemento principale e di usarle per dare uno stile agli elementi figlio e poiché queste proprietà sono ereditate dobbiamo semplicemente modificarle all'interno dell'elemento principale al passaggio del mouse.

Ecco un esempio:

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

Perché questo può essere migliore dell'utilizzo di un selettore specifico combinato con il passaggio del mouse?

Sono in grado di fornire almeno 2 motivi che rendono questo metodo un buon fattore da considerare:

  1. Se abbiamo molti elementi nidificati che condividono gli stessi stili, questo ci eviterà un selettore complesso per indirizzarli tutti al passaggio del mouse. Usando le proprietà personalizzate, cambiamo semplicemente il valore quando si passa con il mouse sull'elemento genitore.
  2. Una proprietà personalizzata può essere utilizzata per sostituire un valore di qualsiasi proprietà e anche un suo valore parziale. Per esempio possiamo definire una proprietà personalizzata per un colore e lo usiamo all'interno di una border, linear-gradient, background-color, box-shadowecc Questo eviterà noi resettare tutte queste proprietà al passaggio del mouse.

Ecco un esempio più complesso:

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

Come possiamo vedere sopra, abbiamo solo bisogno di una dichiarazione CSS per cambiare molte proprietà di diversi elementi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.