Efecto de enfoque de galería CSS puro con :not | trucos CSS
A menudo, en el pasado, tenía que descubrir cómo agregar estilos a todos los elementos del contenedor, pero no el que flota.
Este efecto requiere seleccionar los hermanos de un elemento retenido. Solía implementar JavaScript para esto agregando o eliminando la clase que define las reglas CSS correctas de mouseenter
y mouseleave
eventos similares a este:
Aunque el código funciona, mi instinto siempre me dijo que debe haber alguna forma de CSS puro para lograr el mismo resultado.Hace unos años, mientras trabajaba en un cierto control deslizante para mi empresa, se me ocurrió una solución similar a la que Chris Geelhoed Recreé la famosa animación en la página de inicio de Netflix y me di cuenta de que ya no necesitaba JavaScript para esto.
Hace unos meses estaba tratando de implementar el mismo enfoque para un feed basado en cuadrículas en el sitio web de mi empresa y, boom, ¡no funcionó debido a la diferencia entre los elementos!
Por suerte para mí, resultó que no tenía por qué permanecer así y, de nuevo, no necesité JavaScript para ello.
Marcado y CSS básico
Comencemos a codificar preparando el marcado adecuado:
.grid
está basado en la red<ul>
una lista;- y
.grid__child
los elementos son<li>
niños con los que queremos comunicarnos.
El marcado se ve así:
<ul class="grid">
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
</ul>
El estilo debería verse así:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 15rem);
grid-gap: 1rem;
}
.grid__child {
background: rgba(0, 0, 0, .1);
border-radius: .5rem;
aspect-ratio: 1/1;
}
Este código de ejemplo creará tres elementos de lista que ocupan tres columnas en una cuadrícula.
El poder de los selectores CSS
Ahora agreguemos un poco de interactividad. El enfoque que implementé originalmente se basó en dos pasos:
- pasar el cursor sobre el contenedor debería cambiar los estilos de todos los elementos dentro...
- ... excepto por el que el cursor se está moviendo actualmente.
Comencemos agarrando a cada niño a medida que el cursor se mueve sobre el contenedor:
.grid:hover .grid__child {
/* ... */
}
En segundo lugar, apaguemos el elemento sobre el que se muestra actualmente y alejemos opacity
a cualquier otro niño:
.grid:hover .grid__child:not(:hover) {
opacity: 0.3;
}
Y esto sería suficiente para contenedores sin espacios entre elementos secundarios:
Sin embargo, en mi caso no pude eliminar estos vacíos:
Cuando moví el mouse entre los mosaicos, todos los elementos secundarios se desvanecieron.
Ignorar espacios
Podemos suponer que los huecos son partes del contenedor que sus elementos secundarios no superponen. No queremos activar el efecto cada vez que el cursor ingresa al contenedor, sino cuando pasa sobre uno de los elementos del interior. ¿Podemos ignorar que el cursor se mueve sobre los espacios?
Sí, podemos, usando pointer-events: none
en .grid
recipiente y devuélvalos con pointer-events: auto
sobre sus hijos:
.grid {
/* ... */
pointer-events: none;
}
/* ... */
.grid__child {
/* ... */
pointer-events: auto;
}
Solo agreguemos una transición genial a la opacidad y tenemos un componente listo:
Probablemente sea aún más genial cuando agregamos más mosaicos y creamos un diseño 2D:
El CSS final se ve así:
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 15rem);
grid-gap: 3rem;
pointer-events: none;
}
.grid:hover .grid__child:not(:hover) {
opacity: 0.3;
}
.grid__child {
background: rgba(0, 0, 0, .1);
border-radius: .5rem;
aspect-ratio: 1/1;
pointer-events: auto;
transition: opacity 300ms;
}
¡Con solo 2 líneas adicionales de código, resolvimos el problema de la brecha!
Posibles problemas
Aunque es una solución compacta, hay algunas situaciones en las que pueden ser necesarias algunas soluciones alternativas.
Desafortunadamente, este truco no funcionará cuando desee que el contenedor se pueda desplazar, como en una especie de control deslizante horizontal. pointer-events: none
style ignorará no solo el evento hover, sino también todos los demás. En tales situaciones, puede envolver .grid
en otro contenedor, así:
<div class="container">
<ul class="grid">
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
</ul>
</div>
Resumen
Le recomiendo encarecidamente que experimente y trate de encontrar un enfoque más simple y natural para las tareas que normalmente se espera que tengan cierto nivel de complejidad. Las tecnologías web como CSS son cada vez más potentes y, al usar soluciones nativas listas para usar, puede lograr excelentes resultados sin tener que mantener su código y proporcionarlo a los proveedores de navegadores.
Espero que hayas disfrutado este breve tutorial y lo hayas encontrado útil. ¡Gracias!
El autor eligió técnico educación para recibir una donación como parte de Escribir para donaciones programa.
Deja una respuesta