¿Cómo diseñar el elemento padre al pasar el cursor sobre un elemento hijo?

160

Sé que no existe un selector padre CSS , pero ¿es posible diseñar un elemento padre al pasar el cursor por un elemento hijo sin ese selector?

Para dar un ejemplo: considere un botón de eliminar que cuando se coloca el cursor resaltará el elemento que está a punto de eliminarse:

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

Por medio de CSS puro, ¿cómo cambiar el color de fondo de esta sección cuando el mouse está sobre el botón?

NGLN
fuente
3
Posible duplicado de ¿Hay un selector padre CSS?
TylerH
Posible solución: stackoverflow.com/q/39374918/3597276
Michael Benjamin

Respuestas:

134

Bueno, esta pregunta se hace muchas veces antes, y la respuesta típica corta es: no se puede hacer con CSS puro. Está en el nombre: las hojas de estilo en cascada solo admiten el estilo en dirección en cascada, no hacia arriba.

Pero en la mayoría de las circunstancias donde se desea este efecto, como en el ejemplo dado, todavía existe la posibilidad de utilizar estas características en cascada para alcanzar el efecto deseado. Considere este pseudo marcado:

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

El truco es darle al hermano el mismo tamaño y posición que el padre y darle estilo al hermano en lugar del padre. ¡Esto se verá como si el padre tuviera estilo!

Ahora, ¿cómo peinar al hermano?

Cuando el niño está suspendido, el padre también, pero el hermano no. Lo mismo vale para el hermano. Esto concluye en tres posibles rutas de selector CSS para diseñar el hermano:

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

Estos diferentes caminos permiten algunas buenas posibilidades. Por ejemplo, desencadenar este truco en el ejemplo de la pregunta da como resultado este violín :

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

Ejemplo de imagen principal de estilo

Obviamente, en la mayoría de los casos este truco depende del uso de posicionamiento absoluto para darle al hermano el mismo tamaño que el padre, y aún así dejar que el niño aparezca dentro del padre.

A veces es necesario usar una ruta de selector más calificada para seleccionar un elemento específico, como se muestra en este violín que implementa el truco varias veces en un menú de árbol. Bastante agradable de verdad.

NGLN
fuente
1
Esto es bueno para resaltar, pero no funcionará si intenta cambiar el color de la fuente, ¿estoy en lo cierto?
Jahanzeb Khan
1
@JahanzebKhan Cambiar el color de fuente no es problema .
NGLN
117

Sé que es una vieja pregunta, pero me las arreglé para hacerlo sin un pseudo hijo (sino un pseudo envoltorio).

Si configura el padre para que esté con no pointer-events, y luego un hijo divcon pointer-eventsset para auto, funciona :)
Tenga en cuenta que la <img>etiqueta (por ejemplo) no funciona.
Asimismo, recuerda a fijar pointer-eventsa autolos otros niños que tienen su propio detector de eventos, o de lo contrario van a perder su funcionalidad clic.

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>

Editar:
como Shadow Wizard señaló amablemente: vale la pena mencionar que esto no funcionará para IE10 y versiones posteriores. (Versiones antiguas de FF y Chrome también, ver aquí )

chico_m
fuente
3
Vale la pena mencionar que esto no funcionará para IE10 y a continuación. (Versiones antiguas de FF y Chrome también, ver aquí )
Shadow Wizard is Ear For You
2
¡Establecer eventos de puntero en none también significa que los oyentes de eventos en ese elemento no funcionarán ...!
rhazen
1
@rhazen tienes toda la razón. Aunque, según mi experiencia, este uso generalmente está conectado a un área / elemento de un solo clic, por lo que puede asignar el escucha de clics al padre
guy_m
¿Qué tal si tengo dos niveles, padre, hijo1 e hijo de hijo1. Agregué pointer-events none a parent y pointer-events auto to child. Quiero pasar a child1 excepto el hijo del niño 1. Demostración aquí: codepen.io/lion5893/pen/WNQgyVx
Nam Lê Quý
13

Otro enfoque más simple (a una pregunta anterior) ...
sería colocar elementos como hermanos y usar:

Selector de hermano adyacente ( +) o Selector de hermano general ( ~)

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

ingrese la descripción de la imagen aquí

Demo Fiddle aquí .

Onur Yıldırım
fuente
1
Vale la pena señalar que esto solo funciona. #Los objetivos vienen después de #control en el DOM (es decir, no puede afectar a los hermanos anteriores, solo a los siguientes)
Gio
10

no hay un selector CSS para seleccionar un padre de un niño seleccionado.

podrías hacerlo con JavaScript

Kae Verens
fuente
3
cierto. algo así como $ (child) .hover (function () {$ (this) .closest (parentSelector) .addClass ('hoverClass')}, function () {$ (this) .closest (parentSelector) .removeClass ('hoverClass' )});
Aamir Afridi
8
@AamirAfridi Sin embargo, eso no es puro JS, debes usar jQuery con eso.
Ivotje50
6

Como se mencionó anteriormente, "no hay un selector CSS para seleccionar un padre de un hijo seleccionado".

Entonces tú tampoco:


Aquí está el ejemplo de la solución javascript / jQuery

En el lado de javascript:

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

Y en el lado de CSS, tendrías algo como esto:

.is-hover {
  background-color: red;
}
Remy Lagerweij
fuente
3

Esta solución depende completamente del diseño, pero si tiene un div padre en el que desea cambiar el fondo al pasar el mouse sobre un niño, puede intentar imitar al padre con un ::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: "";
}

Vea un ejemplo completo de violín aquí

Jan Mellström
fuente
-1

Una solución jquery simple para aquellos que no necesitan una solución CSS pura:

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

¡Esto es extremadamente fácil de hacer en Sass! No profundice en JavaScript para esto. El & selector en sass hace exactamente esto.

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

admazzola
fuente
66
-1 Sass no agrega más funcionalidad a css, solo facilita la escritura. Todo lo que puede hacer en sass se puede hacer en css y viceversa.
Dastur
3
@Dastur Dadas las variables y mixins, diría que Sass agrega muchísimo a CSS. Puede hacerlo todo en CSS, de la misma manera que aún podría escribir software sofisticado utilizando el viejo C. Los lenguajes modernos agregan mucho sin habilitar algo que no se podía hacer antes. Lo mismo con Sass y CSS.
Cobus Kruger el
66
@ Cobus Kruger Tienes razón en parte, pero no puedes hacer esa comparación. Mientras que lenguajes como c ++ c # y javascript pueden estar basados ​​en C, no se convierten en C antes del tiempo de ejecución. Sass se convierte en CSS antes del tiempo de ejecución, por lo tanto, nunca se carga realmente una hoja de estilo Sass, solo una CSS.
Dastur