En ren CSS Gallery Focus Effect med :not

Kildeknude: 1723238

Tidligere havde jeg ofte brug for at finde ud af, hvordan man tilføjer stilarter til alle elementer inde i beholderen, men ikke den svævede.

Demo af den forventede "fade-out"-effekt på søskende for at lade brugerne "fokusere" på et bestemt element.

Denne effekt kræver, at man vælger søskende til et svævende element. Jeg plejede at anvende JavaScript til dette ved at tilføje eller fjerne den klasse, der definerede de korrekte CSS-regler for mouseenter , mouseleave begivenheder, der ligner denne:

Selvom koden gør tricket, fortalte min mavefornemmelse mig altid, at der skal være en ren CSS måde at opnå det samme resultat på. For et par år siden, mens jeg arbejdede på en bestemt skyder for mit firma, fandt jeg på en løsning svarende til hvordan Chris Geelhoed genskabte den berømte Netflix-hjemmesideanimation og jeg forstod, at jeg ikke havde brug for JavaScript til dette længere.

For et par måneder siden prøvede jeg at implementere den samme tilgang til et netbaseret feed på min virksomheds hjemmeside, og – boom – det virkede ikke på grund af kløften mellem elementerne!

Heldigvis for mig viste det sig, at det ikke behøvede at forblive sådan her, og endnu en gang havde jeg ikke brug for JavaScript til det.

Markup og basis CSS

Lad os begynde at kode ved at forberede den korrekte opmærkning:

  • .grid er en grid-baseret

      liste;

    • , .grid__child elementer er
    • børn, som vi gerne vil omgås.

    Opmærkningen ser sådan ud:

    Stilen skal se sådan ud:

    .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 eksempelkode vil oprette tre listeelementer, der optager tre kolonner i et gitter.

    Kraften i CSS-vælgere

    Lad os nu tilføje noget interaktivitet. Den tilgang, som jeg oprindeligt anvendte, var baseret på to trin:

    1. At svæve på beholderen skulle ændre stilene for alle elementer inde i...  
    2. …undtagen den, hvor markøren svæver i øjeblikket.

    Lad os starte med at gribe hvert barn, mens markøren svæver over beholderen:

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

    For det andet, lad os udelukke det aktuelt svævende element og reducere opacity af ethvert andet barn:

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

    Og dette ville være perfekt nok til beholdere uden mellemrum mellem underelementerne:

    Animeret GIF af en musemarkør, der interagerer med elementer, der ikke er adskilt af mellemrum.
    Demo af en løsning, der fungerer uden huller.

    I mit tilfælde kunne jeg dog ikke fjerne disse huller:

    Animeret GIF af en musemarkør, der svæver over elementer. Men når musen går ind i et mellemrum mellem to elementer, ophører effekten, når musen forlader elementet.
    Demo af problemet, der opstår, når huller er indført.

    Da jeg flyttede musen mellem fliserne, var alle børneelementerne ved at falme ud.

    Ignorerer hullerne

    Vi kan antage, at huller er dele af beholderen, som ikke er overlejret af dens børn. Vi ønsker ikke at køre effekten hver gang markøren kommer ind i beholderen, men snarere når den svæver over et af elementerne indeni. Kan vi så ignorere, at markøren bevæger sig over hullerne? 

    Ja, det kan vi, vha pointer-events: none på den .grid container og bringe dem tilbage med pointer-events: auto på sine børn:

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

    Lad os bare tilføje en cool overgang til opacitet, og vi har en klar komponent:

    Det er nok endnu sejere, når vi tilføjer flere fliser og skaber et 2-dimensionelt layout:

    Den endelige CSS ser sådan ud:

    .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 kun 2 ekstra linjer kode overvandt vi hulproblemet!

    Mulige problemer

    Selvom det er en kompakt løsning, er der nogle situationer, hvor det kan kræve nogle løsninger.

    Desværre virker dette trick ikke, når du ønsker, at beholderen skal kunne rulles, f.eks. i en form for vandret skyder. Det pointer-events: none stil ville ignorere ikke kun hover-begivenheden, men også alle de andre. I sådanne situationer kan du pakke ind .grid i en anden beholder, som denne:

    Resumé

    Jeg opfordrer dig kraftigt til at eksperimentere og prøve at finde en enklere og mere indbygget tilgang til opgaver, der normalt forventes at have en vis grad af kompleksitet. Webteknologier, som CSS, bliver mere og mere kraftfulde, og ved at bruge out-of-the-box native løsninger kan du opnå fantastiske resultater uden at skulle vedligeholde din kode og afgive den til browserleverandører.

    Jeg håber, at du kunne lide denne korte tutorial og fandt den nyttig. Tak!

    Forfatteren valgte Tech Uddannelse at modtage en donation som en del af Skriv for donationer program.

    Tidsstempel:

    Mere fra CSS-tricks