Un efect pur de focalizare în galerie CSS cu :not

Nodul sursă: 1723238

Deseori, în trecut, trebuia să-mi dau seama cum să adaug stiluri tuturor elementelor din interiorul containerului, dar nu cel planat.

Demonstrație a efectului de „fade-out” așteptat asupra fraților, pentru a permite utilizatorilor să „se concentreze” pe un anumit element.

Acest efect necesită selectarea fraților unui element hoverat. Obișnuiam să aplic JavaScript pentru asta, adăugând sau eliminând clasa care a definit regulile CSS adecvate mouseenter și mouseleave evenimente, similare cu aceasta:

Deși codul face șmecheria, sentimentul meu mi-a spus întotdeauna că trebuie să existe o modalitate pur-CSS de a obține același rezultat. Acum câțiva ani, în timp ce lucram la un anumit slider pentru compania mea, am venit cu o soluție similară cu cum Chris Geelhoed a recreat celebra animație de pe pagina de pornire Netflix și am înțeles că nu mai am nevoie de JavaScript pentru asta.

Cu câteva luni în urmă, încercam să implementez aceeași abordare a unui flux bazat pe grilă pe site-ul companiei mele și — boom — nu a funcționat din cauza decalajului dintre elemente!

Din fericire pentru mine, s-a părut că nu trebuie să rămână așa și încă o dată nu am avut nevoie de JavaScript pentru el.

Markup și CSS de bază

Să începem codificarea pregătind marcajul corespunzător:

  • .grid este o grilă

      listă;

    • și .grid__child elementele sunt
    • copiii cu care dorim să interacționăm.

    Markup-ul arată astfel:

    Stilul ar trebui să arate astfel:

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

    Acest exemplu de cod va crea trei elemente de listă care ocupă trei coloane într-o grilă.

    Puterea selectoarelor CSS

    Acum, să adăugăm puțină interactivitate. Abordarea pe care am aplicat-o inițial sa bazat pe doi pași:

    1. Plasarea pe container ar trebui să schimbe stilurile tuturor elementelor din interior...  
    2. ...cu excepția celui pe care cursorul se află în acest moment.

    Să începem prin a lua fiecare copil în timp ce cursorul trece peste container:

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

    În al doilea rând, să excludem elementul plasat în prezent și să reducem opacity a oricărui alt copil:

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

    Și acest lucru ar fi suficient pentru containerele fără spații între elementele copil:

    GIF animat al cursorului mouse-ului care interacționează cu elemente care nu sunt separate de niciun spațiu.
    Demo a unei soluții care funcționează fără lacune.

    Cu toate acestea, în cazul meu, nu am putut elimina aceste lacune:

    GIF animat al unui cursor al mouse-ului care trece peste elemente. Cu toate acestea, atunci când mouse-ul intră într-un spațiu între două elemente, efectul se termină pe măsură ce mouse-ul părăsește elementul.
    Demostrare a problemei întâlnite atunci când sunt introduse lacune.

    Când mișcam mouse-ul între plăci, toate elementele copiilor dispăreau.

    Ignorând golurile

    Putem presupune că golurile sunt părți ale recipientului care nu sunt suprapuse de copiii acestuia. Nu vrem să rulăm efectul de fiecare dată când cursorul intră în container, ci mai degrabă atunci când trece peste unul dintre elementele din interior. Putem ignora atunci deplasarea cursorului deasupra golurilor? 

    Da, putem, folosind pointer-events: none pe .grid recipient și aducându-le înapoi cu pointer-events: auto asupra copiilor săi:

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

    Să adăugăm doar o tranziție cool asupra opacității și avem o componentă gata:

    Probabil că este și mai tare când adăugăm mai multe plăci și creăm un aspect bidimensional:

    CSS-ul final arată astfel:

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

    Cu doar 2 linii suplimentare de cod am depășit problema decalajului!

    Probleme posibile

    Deși este o soluție compactă, există unele situații în care ar putea necesita unele soluții.

    Din păcate, acest truc nu va funcționa atunci când doriți ca containerul să poată fi derulat, de exemplu, ca într-un fel de glisor orizontal. The pointer-events: none stilul ar ignora nu numai evenimentul hover, ci și pe toate celelalte. În astfel de situații, puteți împacheta .grid într-un alt recipient, așa:

    Rezumat

    Vă încurajez cu tărie să experimentați și să încercați să găsiți o abordare mai simplă și mai nativă pentru sarcinile despre care, de obicei, se așteaptă să aibă un anumit nivel de complexitate. Tehnologiile web, cum ar fi CSS, devin din ce în ce mai puternice și, folosind soluții native ieșite din cutie, puteți obține rezultate excelente fără a fi nevoie să vă mențineți codul și să-l cedați furnizorilor de browsere.

    Sper că ți-a plăcut acest scurt tutorial și că l-ai găsit util. Mulțumiri!

    Autorul a selectat Tech Educaţie pentru a primi o donație ca parte a Scrieți pentru donații programul.

    Timestamp-ul:

    Mai mult de la CSS Trucuri