Un effet de focus de galerie CSS pur avec : not

Nœud source: 1723238

Souvent, dans le passé, j'avais besoin de comprendre comment ajouter des styles à tous les éléments à l'intérieur du conteneur, mais ne sauraient celui plané.

Démonstration de l'effet de "fondu" attendu sur les frères et sœurs pour permettre aux utilisateurs de "se concentrer" sur un élément particulier.

Cet effet nécessite de sélectionner les frères et sœurs d'un élément survolé. J'avais l'habitude d'appliquer JavaScript pour cela, en ajoutant ou en supprimant la classe qui définissait les règles CSS appropriées sur mouseenter ainsi que mouseleave événements similaires à celui-ci :

Bien que le code fasse l'affaire, mon intuition m'a toujours dit qu'il devait y avoir un moyen purement CSS pour obtenir le même résultat. Il y a quelques années, alors que je travaillais sur un certain curseur pour mon entreprise, j'ai trouvé une solution similaire à comment Chris Geelhoed a recréé la célèbre animation de la page d'accueil de Netflix et j'ai compris que je n'avais plus besoin de JavaScript pour cela.

Il y a quelques mois, j'essayais de mettre en œuvre la même approche pour un flux basé sur une grille sur le site Web de mon entreprise et - boum - cela n'a pas fonctionné à cause de l'écart entre les éléments !

Heureusement pour moi, il est apparu que cela ne devait pas rester comme ça, et encore une fois, je n'avais pas besoin de JavaScript pour cela.

Balisage et CSS de base

Commençons à coder en préparant le balisage approprié :

  • .grid est basé sur une grille

      liste;

    • ainsi que .grid__child les éléments sont
    • enfants avec qui nous voulons interagir.

    Le balisage ressemble à ceci :

    Le style devrait ressembler à ceci :

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

    Cet exemple de code créera trois éléments de liste occupant trois colonnes dans une grille.

    La puissance des sélecteurs CSS

    Maintenant, ajoutons un peu d'interactivité. L'approche que j'ai initialement appliquée reposait sur deux étapes :

    1. le survol du conteneur devrait changer les styles de tous les éléments à l'intérieur…  
    2. … sauf celui que le curseur survole en ce moment.

    Commençons par saisir chaque enfant pendant que le curseur survole le conteneur :

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

    Deuxièmement, excluons l'élément actuellement survolé et réduisons le opacity de tout autre enfant :

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

    Et ce serait parfaitement suffisant pour les conteneurs sans espaces entre les éléments enfants :

    GIF animé d'un curseur de souris interagissant avec des éléments qui ne sont séparés par aucun espace.
    Démo d'une solution qui fonctionne sans lacunes.

    Cependant, dans mon cas, je n'ai pas pu supprimer ces lacunes:

    GIF animé d'un curseur de souris survolant des éléments. Cependant, lorsque la souris entre dans un espace entre deux éléments, l'effet se termine lorsque la souris quitte l'élément.
    Démonstration du problème rencontré lors de l'introduction de lacunes.

    Lorsque je déplaçais la souris entre les tuiles, tous les éléments enfants disparaissaient.

    Ignorer les lacunes

    Nous pouvons supposer que les lacunes sont des parties du conteneur qui ne sont pas recouvertes par ses enfants. Nous ne voulons pas exécuter l'effet chaque fois que le curseur entre dans le conteneur, mais plutôt lorsqu'il survole l'un des éléments à l'intérieur. Pouvons-nous alors ignorer le déplacement du curseur au-dessus des espaces ? 

    Oui, nous pouvons, en utilisant pointer-events: none sur le .grid conteneur et les ramener avec pointer-events: auto sur ses enfants :

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

    Ajoutons simplement une transition sympa sur l'opacité et nous avons un composant prêt :

    C'est probablement encore plus cool lorsque nous ajoutons plus de tuiles et créons une mise en page en 2 dimensions :

    Le CSS final ressemble à ceci :

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

    Avec seulement 2 lignes de code supplémentaires, nous avons surmonté le problème d'écart !

    Problèmes possibles

    Bien qu'il s'agisse d'une solution compacte, certaines situations peuvent nécessiter des solutions de contournement.

    Malheureusement, cette astuce ne fonctionnera pas si vous voulez que le conteneur soit déroulant, par exemple, comme dans une sorte de curseur horizontal. Le pointer-events: none style ignorerait non seulement l'événement de survol mais aussi tous les autres. Dans de telles situations, vous pouvez envelopper le .grid dans un autre conteneur, comme ceci :

    Résumé

    Je vous encourage fortement à expérimenter et à essayer de trouver une approche plus simple et plus native pour les tâches qui sont généralement censées avoir un certain niveau de complexité. Les technologies Web, comme CSS, deviennent de plus en plus puissantes et en utilisant des solutions natives prêtes à l'emploi, vous pouvez obtenir d'excellents résultats sans avoir à maintenir votre code et à le céder aux fournisseurs de navigateurs.

    J'espère que vous avez aimé ce court tutoriel et que vous l'avez trouvé utile. Merci!

    L'auteur a choisi le Technologie Éducation recevoir un don dans le cadre de Ecrire pour DOnations .

    Horodatage:

    Plus de Astuces CSS