Een puur CSS-galerijfocuseffect met :not

Bronknooppunt: 1723238

In het verleden moest ik vaak uitzoeken hoe ik stijlen aan alle elementen in de container kon toevoegen, maar niet de zweefde.

Demo van het verwachte "fade-out"-effect op broers en zussen om gebruikers te laten "focussen" op een bepaald element.

Voor dit effect moeten de broers en zussen van een zwevend element worden geselecteerd. Ik paste hiervoor JavaScript toe, waarbij ik de klasse toevoeg of verwijderde die de juiste CSS-regels definieerde mouseenter en mouseleave evenementen, vergelijkbaar met deze:

Hoewel de code werkt, zei mijn onderbuikgevoel me altijd dat er een pure CSS-manier moest zijn om hetzelfde resultaat te bereiken. Een paar jaar geleden, terwijl ik aan een bepaalde slider voor mijn bedrijf werkte, kwam ik met een oplossing die lijkt op: hoe Chris Geelhoed de beroemde Netflix-homepage-animatie opnieuw maakte en ik begreep dat ik hier geen JavaScript meer voor nodig had.

Een paar maanden geleden probeerde ik dezelfde benadering van een op rasters gebaseerde feed op mijn bedrijfswebsite te implementeren en - boem - het werkte niet vanwege de kloof tussen de elementen!

Gelukkig voor mij bleek dat het niet zo hoeft te blijven, en wederom had ik er geen JavaScript voor nodig.

Markup en basis-CSS

Laten we beginnen met coderen door de juiste opmaak voor te bereiden:

  • .grid is een op rasters gebaseerd

      lijst;

    • en .grid__child elementen zijn
    • kinderen waarmee we willen omgaan.

    De opmaak ziet er als volgt uit:

    De stijl zou er als volgt uit moeten zien:

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

    Met deze voorbeeldcode worden drie lijstitems gemaakt die drie kolommen in een raster bezetten.

    De kracht van CSS-kiezers

    Laten we nu wat interactiviteit toevoegen. De aanpak die ik in eerste instantie toepaste was gebaseerd op twee stappen:

    1. zweven op de container zou de stijlen van alle elementen binnenin moeten veranderen ...  
    2. ...behalve degene die de cursor op dit moment zweeft.

    Laten we beginnen met het grijpen van elk kind terwijl de cursor over de container zweeft:

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

    Ten tweede, laten we het huidige zwevende item uitsluiten en de opacity van een ander kind:

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

    En dit zou perfect genoeg zijn voor containers zonder openingen tussen de onderliggende elementen:

    Geanimeerde GIF van een muiscursor die interageert met elementen die niet worden gescheiden door gaten.
    Demo van een oplossing die werkt zonder hiaten.

    In mijn geval kon ik deze hiaten echter niet verwijderen:

    Geanimeerde GIF van een muiscursor die over elementen zweeft. Wanneer de muis echter een opening tussen twee elementen binnengaat, eindigt het effect wanneer de muis het element verlaat.
    Demo van het probleem dat zich voordoet wanneer hiaten worden geïntroduceerd.

    Toen ik de muis tussen de tegels bewoog, vervaagden alle kinderelementen.

    De hiaten negeren

    We kunnen aannemen dat hiaten delen van de container zijn die niet worden bedekt door zijn kinderen. We willen het effect niet elke keer uitvoeren wanneer de cursor de container binnengaat, maar eerder wanneer het over een van de elementen erin zweeft. Kunnen we dan negeren dat de cursor boven de gaten beweegt? 

    Ja, dat kunnen we, met behulp van pointer-events: none op de .grid container en breng ze terug met pointer-events: auto op zijn kinderen:

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

    Laten we gewoon een coole overgang toevoegen aan de dekking en we hebben een kant-en-klaar onderdeel:

    Het is waarschijnlijk nog cooler als we meer tegels toevoegen en een 2-dimensionale lay-out maken:

    De uiteindelijke CSS ziet er als volgt uit:

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

    Met slechts 2 extra regels code hebben we het gap-probleem overwonnen!

    Mogelijke problemen

    Hoewel het een compacte oplossing is, zijn er enkele situaties waarin dit mogelijk een tijdelijke oplossing vereist.

    Helaas werkt deze truc niet als je wilt dat de container schuifbaar is, bijvoorbeeld in een soort horizontale schuifregelaar. De pointer-events: none stijl zou niet alleen de hover-gebeurtenis negeren, maar ook alle andere. In dergelijke situaties kunt u de .grid in een andere container, zoals deze:

    Samengevat

    Ik moedig je ten zeerste aan om te experimenteren en te proberen een eenvoudigere en meer native benadering te vinden voor taken waarvan gewoonlijk wordt verwacht dat ze een zekere mate van complexiteit hebben. Webtechnologieën, zoals CSS, worden steeds krachtiger en door gebruik te maken van kant-en-klare native oplossingen kunt u geweldige resultaten behalen zonder dat u uw code hoeft te onderhouden en af ​​te staan ​​aan browserleveranciers.

    Ik hoop dat je deze korte tutorial leuk vond en nuttig vond. Bedankt!

    De auteur selecteerde de Tech Onderwijs  om een ​​donatie te ontvangen als onderdeel van de Schrijf voor donaties programma.

    Tijdstempel:

    Meer van CSS-trucs