Un efecto de enfoque de galería CSS puro con :not

Nodo de origen: 1723238

A menudo, en el pasado, necesitaba descubrir cómo agregar estilos a todos los elementos dentro del contenedor, pero no el revoloteado.

Demostración del efecto esperado de "desvanecimiento" en los hermanos para permitir que los usuarios "se concentren" en un elemento en particular.

Este efecto requiere seleccionar los hermanos de un elemento flotante. Solía ​​​​aplicar JavaScript para esto, agregando o eliminando la clase que definía las reglas CSS adecuadas en mouseenter y mouseleave eventos, similar a esto:

Aunque el código funciona, mi intuición siempre me dijo que debe haber alguna forma de CSS puro para lograr el mismo resultado. Hace unos años, mientras trabajaba en cierto control deslizante para mi empresa, se me ocurrió una solución similar a cómo Chris Geelhoed recreó la famosa animación de la página de inicio de Netflix y entendí que ya no necesitaba JavaScript para esto.

Hace un par de 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 brecha entre los elementos!

Por suerte para mí, parecía que no tenía por qué quedarse así y, una vez más, no necesitaba JavaScript para ello.

Marcado y CSS base

Comencemos a codificar preparando el marcado adecuado:

  • .grid es una red basada

      lista;

    • y .grid__child los elementos son
    • niños con los que queremos interactuar.

    El marcado se ve así:

    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 algo de interactividad. El enfoque que apliqué inicialmente se basó en dos pasos:

    1. pasar el cursor sobre el contenedor debería cambiar los estilos de todos los elementos dentro...  
    2. …excepto en el que el cursor está flotando en este momento.

    Empecemos agarrando a cada niño mientras el cursor se cierne sobre el contenedor:

    .grid:hover .grid__child {
      /* ... */
    }

    En segundo lugar, excluyamos el elemento actual y reduzcamos el opacity de cualquier otro niño:

    .grid:hover .grid__child:not(:hover) {
      opacity: 0.3;
    }

    Y esto sería perfectamente suficiente para contenedores sin espacios entre los elementos secundarios:

    GIF animado de un cursor de mouse interactuando con elementos que no están separados por espacios.
    Demostración de una solución que funciona sin lagunas.

    Sin embargo, en mi caso, no pude eliminar estas lagunas:

    GIF animado de un cursor de mouse sobre elementos. Sin embargo, cuando el mouse ingresa en un espacio entre dos elementos, el efecto finaliza cuando el mouse abandona el elemento.
    Demostración del problema encontrado cuando se introducen brechas.

    Cuando movía el mouse entre los mosaicos, todos los elementos secundarios se desvanecían.

    Ignorando las lagunas

    Podemos suponer que los huecos son partes del contenedor que no están superpuestas por sus elementos secundarios. No queremos ejecutar el efecto cada vez que el cursor ingresa al contenedor, sino cuando se desplaza sobre uno de los elementos del interior. ¿Podemos ignorar el cursor que se mueve sobre los espacios entonces? 

    Sí, podemos, usando pointer-events: none en .grid contenedor y traerlos de vuelta con pointer-events: auto sobre sus hijos:

    .grid {
      /* ... */
      pointer-events: none;
    }
    
    /* ... */
    
    .grid__child {
      /* ... */
      pointer-events: auto;
    }

    Solo agreguemos una transición genial en la opacidad y tenemos un componente listo:

    Probablemente sea aún más genial cuando agregamos más mosaicos y creamos un diseño bidimensional:

    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 superamos el problema de la brecha!

    Posibles problemas

    Aunque es una solución compacta, hay algunas situaciones en las que podría requerir algunas soluciones.

    Desafortunadamente, este truco no funcionará cuando desee que el contenedor sea desplazable, por ejemplo, como en algún tipo de control deslizante horizontal. los pointer-events: none style ignoraría no solo el evento hover, sino también todos los demás. En tales situaciones, puede envolver el .grid en otro contenedor, así:

    Resumen

    Le recomiendo encarecidamente que experimente y trate de encontrar un enfoque más simple y nativo para las tareas que normalmente se espera que tengan cierto nivel de complejidad. Las tecnologías web, como CSS, son cada vez más poderosas y, al usar soluciones nativas listas para usar, puede lograr excelentes resultados sin la necesidad de mantener su código y cederlo a los proveedores de navegadores.

    Espero que les haya gustado este breve tutorial y lo hayan encontrado útil. ¡Gracias!

    El autor seleccionó el Tecnología. Educación para recibir una donación como parte de la Escribir para donaciones .

    Sello de tiempo:

    Mas de Trucos CSS