En ren CSS Gallery Focus Effect med :not

Kilde node: 1723238

Ofte i det siste trengte jeg å finne ut hvordan jeg kunne legge til stiler til alle elementene inne i beholderen, men ikke den svevende.

Demo av den forventede "fade-out"-effekten på søsken for å la brukere "fokusere" på et bestemt element.

Denne effekten krever at du velger søsken til et element som svever. Jeg pleide å bruke JavaScript for dette, legge til eller fjerne klassen som definerte de riktige CSS-reglene på mouseenter og mouseleave hendelser som ligner på dette:

Selv om koden gjør susen, fortalte magefølelsen meg meg alltid at det må være en ren CSS-måte for å oppnå det samme resultatet. For noen år siden, mens jeg jobbet med en bestemt glidebryter for firmaet mitt, kom jeg opp med en løsning som ligner på hvordan Chris Geelhoed gjenskapte den berømte Netflix-hjemmesideanimasjonen og jeg forsto at jeg ikke trengte JavaScript for dette lenger.

For et par måneder siden prøvde jeg å implementere den samme tilnærmingen til en nettbasert feed på firmaets nettsted, og – boom – det fungerte ikke på grunn av gapet mellom elementene!

Heldigvis for meg så det ut til at det ikke trenger å forbli slik, og nok en gang trengte jeg ikke JavaScript for det.

Markup og base CSS

La oss begynne å kode ved å forberede riktig markering:

  • .grid er et rutenettbasert

      liste;

    • og .grid__child elementene er
    • barn som vi ønsker å samhandle med.

    Markeringen ser slik ut:

    Stilen skal se slik ut:

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

    Denne eksempelkoden vil lage tre listeelementer som opptar tre kolonner i et rutenett.

    Kraften til CSS-velgere

    La oss nå legge til litt interaktivitet. Tilnærmingen jeg først brukte var basert på to trinn:

    1. å sveve på beholderen bør endre stilene til alle elementene inni ...  
    2. … bortsett fra den som markøren svever for øyeblikket.

    La oss begynne med å gripe hvert barn mens markøren svever over beholderen:

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

    For det andre, la oss ekskludere det gjeldende elementet og redusere opacity av ethvert annet barn:

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

    Og dette ville være perfekt nok for beholdere uten mellomrom mellom underelementene:

    Animert GIF av en musepeker som samhandler med elementer som ikke er atskilt med hull.
    Demo av en løsning som fungerer uten hull.

    Men i mitt tilfelle kunne jeg ikke fjerne disse hullene:

    Animert GIF av en musepeker som svever over elementer. Men når musen går inn i et gap mellom to elementer, slutter effekten når musen forlater elementet.
    Demo av problemet som oppstår når hull blir introdusert.

    Da jeg flyttet musen mellom flisene, ble alle barneelementene ut.

    Ignorerer hullene

    Vi kan anta at hull er deler av beholderen som ikke er overlagt av barna. Vi ønsker ikke å kjøre effekten hver gang markøren går inn i beholderen, men snarere når den svever over et av elementene inni. Kan vi ignorere at markøren beveger seg over hullene da? 

    Ja, vi kan bruke pointer-events: none.grid beholderen og ta dem med tilbake pointer-events: auto på sine barn:

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

    La oss bare legge til en kul overgang på opasitet, og vi har en klar komponent:

    Det er sannsynligvis enda kulere når vi legger til flere fliser og lager en 2-dimensjonal layout:

    Den endelige CSS ser slik ut:

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

    Med bare 2 ekstra linjer med kode overvant vi gap-problemet!

    Mulige problemer

    Selv om det er en kompakt løsning, er det noen situasjoner der det kan kreve noen løsninger.

    Dessverre vil ikke dette trikset fungere når du vil at beholderen skal være rullbar, for eksempel som i en slags horisontal skyveknapp. De pointer-events: none stil ville ignorere ikke bare svevehendelsen, men alle de andre også. I slike situasjoner kan du pakke inn .grid i en annen beholder, slik:

    Oppsummering

    Jeg oppfordrer deg sterkt til å eksperimentere og prøve å finne en enklere og mer naturlig tilnærming for oppgaver som vanligvis forventes å ha en viss grad av kompleksitet. Nettteknologier, som CSS, blir kraftigere og kraftigere, og ved å bruke originale løsninger kan du oppnå flotte resultater uten å måtte vedlikeholde koden din og gi den til nettleserleverandører.

    Jeg håper du likte denne korte opplæringen og fant den nyttig. Takk!

    Forfatteren valgte Tech Kunnskap å motta en donasjon som en del av Skriv for donasjoner program.

    Tidstempel:

    Mer fra CSS triks