Cómo afectar a otros elementos cuando un elemento está suspendido

459

Lo que quiero hacer es que cuando un cierto divestá suspendido, afectaría las propiedades de otro div.

Por ejemplo, en esta demostración de JSFiddle , cuando pasa el mouse sobre #cubeél, cambia, background-colorpero lo que quiero es que cuando pase el mouse #container, #cubese vea afectado.

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
fuente

Respuestas:

987

Si el cubo está directamente dentro del contenedor:

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

Si el cubo está al lado (después de que los contenedores cierren la etiqueta) del contenedor:

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

Si el cubo está en algún lugar dentro del contenedor:

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

Si el cubo es hermano del contenedor:

#container:hover ~ #cube { background-color: yellow; }
Miguel
fuente
107
No olvide el combinador general de hermanos ~para 'el cubo está en algún lugar después del contenedor en el DOM y comparte un padre'
robertc
3
Eso es muy bonito. ¿Hay alguna fuente donde pueda encontrar más información al respecto? ¿Es compatible con todos los navegadores, es CSS3? Sería genial tener más información sobre eso. ¡Muchas gracias!
Anónimo
2
+1 Gran respuesta @ Mike. ¿Qué pasa si #containerestá al lado #cube, es decir, #containersigue #cube?
PeterKA
44
¿Qué hacer si el elemento suspendido está dentro del contenedor (que queremos que se efectúe)? Por ejemplo: #cube: hover #container {Algunos efectos CSS}
Hanzallah Afgan
2
Buena respuesta !! ¿Qué pasa si quiero cambiar el padre cuando paso el mouse sobre el niño? Creo que no hay selector para eso.
Mikel
41

En este ejemplo particular, puede usar:

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

Este ejemplo solo funciona ya que cubees hijo de container. Para escenarios más complicados, necesitaría usar CSS diferente o JavaScript.

Emmett
fuente
35

El uso del selector de hermanos es la solución general para diseñar otros elementos al pasar el mouse sobre uno determinado, pero solo funciona si los otros elementos siguen al dado en el DOM . ¿Qué podemos hacer cuando los otros elementos deberían estar realmente antes que el que está suspendido? Digamos que queremos implementar un widget de calificación de barra de señal como el siguiente:

Widget de calificación de barra de señal

En realidad, esto se puede hacer fácilmente usando el modelo CSS flexbox, estableciéndolo flex-directionen reverse, para que los elementos se muestren en el orden opuesto al que están en el DOM. La captura de pantalla anterior es de dicho widget, implementado con CSS puro.

Flexbox es muy compatible con el 95% de los navegadores modernos.

Dan Dascalescu
fuente
¿Podría esto ser editado para que el resaltado no desaparezca al mover el mouse de una barra a la otra? El parpadeo es un poco molesto.
Cerbrus
@Cerbrus: se agregó una solución que no oculta el desplazamiento cuando el mouse está entre barras. La desventaja es que el ancho de las barras ya no es igual.
Dan Dascalescu
1
Pruebe esto en su primer fragmento: encendido .rating div, elimine el margen y agregueborder-right: 4px solid white;
Cerbrus
1
Dirección de flexión (no es compatible con IE) O 1) negro por defecto 2) todo azul en el mouse sobre el contenedor 3) negro para el próximo hermano en la barra de desplazamiento :)
Stephane Mathis
Hice este violín que (al menos para mí) lo hizo un poco más aparente en lo que estaba sucediendo aquí. jsfiddle.net/maxshuty/cj55y33p/3
maxshuty
8

¡Muchas gracias a Mike y Robertc por sus útiles publicaciones!

Si tiene dos elementos en su HTML y desea :hoversuperar uno y orientar un cambio de estilo en el otro, los dos elementos deben estar directamente relacionados: padres, hijos o hermanos. Esto significa que los dos elementos deben estar uno dentro del otro o ambos deben estar contenidos dentro del mismo elemento más grande.

Quería mostrar las definiciones en un cuadro en el lado derecho del navegador mientras mis usuarios leen mi sitio y :hoversobre los términos resaltados; por lo tanto, no quería que el elemento 'definición' se mostrara dentro del elemento 'texto'.

Casi me doy por vencido y acabo de agregar JavaScript a mi página, ¡pero este es el futuro! ¡No deberíamos tener que aguantar el back sass de CSS y HTML diciéndonos dónde tenemos que colocar nuestros elementos para lograr los efectos que queremos! Al final nos comprometimos.

Si bien los elementos HTML reales en el archivo deben estar anidados o contenidos en un solo elemento para ser :hoverobjetivos válidos entre sí, el positionatributo css se puede usar para mostrar cualquier elemento donde lo desee. Usé position: fixed para colocar el objetivo de mi :hoveracción donde lo quería en la pantalla del usuario, independientemente de su ubicación en el documento HTML.

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

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

En este ejemplo, el objetivo de un :hovercomando de un elemento dentro #explainBoxdebe ser #explainBoxo también dentro #explainBox. Los atributos de posición asignados a #definiciones lo obligan a aparecer en la ubicación deseada (fuera #explainBox) a pesar de que técnicamente se encuentra en una posición no deseada dentro del documento HTML.

Entiendo que se considera una mala forma usar lo mismo #idpara más de un elemento HTML; sin embargo, en este caso, las instancias de #lightpueden describirse independientemente debido a sus respectivas posiciones en #idelementos 'd únicos . ¿Hay alguna razón para no repetirlo id #lighten este caso?

almiar
fuente
Una respuesta bastante larga para un punto tan corto, pero aquí hay un jsfiddle jsfiddle.net/ubershmekel/bWgq6/1
ubershmekel
1
algunos navegadores se asustarán cuando los uses IDvarias veces. Solo usa a class.
Serj Sagan
6

Solo esto funcionó para mí:

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

¿Dónde .cubeestá CssClass de la #cube.

Probado en Firefox , Chrome y Edge .

CyberHawk
fuente
4

Aquí hay otra idea que le permite afectar a otros elementos sin tener en cuenta ningún selector específico y utilizando solo el :hoverestado del elemento principal.

Para esto, confiaré en el uso de propiedades personalizadas (variables CSS). Como podemos leer en la especificación :

Las propiedades personalizadas son propiedades ordinarias , por lo que se pueden declarar en cualquier elemento, se resuelven con la herencia normal y las reglas en cascada ...

La idea es definir propiedades personalizadas dentro del elemento principal y usarlas para diseñar elementos secundarios y dado que estas propiedades se heredan, simplemente necesitamos cambiarlas dentro del elemento principal al pasar el mouse sobre ellas.

Aquí hay un ejemplo:

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

¿Por qué esto puede ser mejor que usar un selector específico combinado con el desplazamiento?

Puedo proporcionar al menos 2 razones que hacen que este método sea bueno para considerar:

  1. Si tenemos muchos elementos anidados que comparten los mismos estilos, esto nos evitará un selector complejo para apuntarlos a todos al pasar el mouse. Usando propiedades personalizadas, simplemente cambiamos el valor al pasar el mouse sobre el elemento padre.
  2. Se puede usar una propiedad personalizada para reemplazar un valor de cualquier propiedad y también un valor parcial de la misma. Por ejemplo, podemos definir una propiedad personalizada para un color y utilizarlo dentro de un border, linear-gradient, background-color, box-shadowetc. Esto nos reseting evitar todas estas propiedades en vuelo estacionario.

Aquí hay un ejemplo más complejo:

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

Como podemos ver arriba, solo necesitamos una declaración CSS para cambiar muchas propiedades de diferentes elementos.

Temani Afif
fuente