In der Vergangenheit musste ich oft herausfinden, wie ich Stile auf alle Elemente innerhalb eines Containers anwenden kann, aber nicht auf das Element, über das gerade die Maus fährt.

Dieser Effekt erfordert die Auswahl der Geschwister eines gehoverten Elements. Früher habe ich dafür JavaScript verwendet, indem ich Klassen hinzugefügt oder entfernt habe, die die richtigen CSS-Regeln bei mouseenter und mouseleave-Ereignissen definierten, ähnlich wie hier
Obwohl der Code den Zweck erfüllt, sagte mir mein Bauchgefühl immer, dass es einen reinen CSS-Weg geben muss, um das gleiche Ergebnis zu erzielen. Vor einigen Jahren, als ich an einem bestimmten Slider für mein Unternehmen arbeitete, kam ich auf eine Lösung, die der von Chris Geelhoed ähnelt, der die berühmte Netflix-Homepage-Animation nachgebildet hat, und mir wurde klar, dass ich dafür kein JavaScript mehr brauche.
Vor ein paar Monaten versuchte ich, denselben Ansatz auf einem gitterbasierten Feed auf der Website meines Unternehmens anzuwenden, und – zack – es funktionierte wegen des Abstands zwischen den Elementen nicht!
Glücklicherweise stellte sich heraus, dass das nicht so bleiben muss, und wieder brauchte ich dafür kein JavaScript.
Markup und Basis-CSS
Beginnen wir mit der Programmierung, indem wir das entsprechende Markup vorbereiten
.gridist eine gitterbasierte<ul>-Liste;- und
.grid__child-Elemente sind<li>-Kinder, mit denen wir interagieren möchten.
Das Markup sieht so aus
<ul class="grid">
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
</ul>
Der Stil sollte so aussehen
.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;
}
Dieser Beispielcode erstellt drei Listenelemente, die drei Spalten in einem Raster belegen.
Die Macht von CSS-Selektoren
Lassen Sie uns nun etwas Interaktivität hinzufügen. Der Ansatz, den ich ursprünglich verfolgte, basierte auf zwei Schritten
- Das Hovern über den Container soll die Stile aller darin enthaltenen Elemente ändern…
- …mit Ausnahme desjenigen, über dem sich der Cursor gerade befindet.
Beginnen wir damit, jedes Kind zu erfassen, während sich der Cursor über dem Container befindet
.grid:hover .grid__child {
/* ... */
}
Zweitens schließen wir das aktuell gehoverte Element aus und reduzieren die opacity aller anderen Kinder
.grid:hover .grid__child:not(:hover) {
opacity: 0.3;
}
Und das wäre absolut ausreichend für Container ohne Lücken zwischen den Kindelementen

In meinem Fall konnte ich diese Lücken jedoch nicht entfernen

Als ich die Maus zwischen den Kacheln bewegte, verblassten alle Kinderelemente.
Lücken ignorieren
Wir können davon ausgehen, dass Lücken Teile des Containers sind, die nicht von seinen Kindern überlagert werden. Wir möchten den Effekt nicht jedes Mal ausführen, wenn der Cursor in den Container fährt, sondern wenn er über eines der Elemente darin fährt. Können wir die Mausbewegung über den Lücken ignorieren?
Ja, das können wir, indem wir pointer-events: none auf dem .grid-Container verwenden und sie mit pointer-events: auto auf seinen Kindern wiederherstellen
.grid {
/* ... */
pointer-events: none;
}
/* ... */
.grid__child {
/* ... */
pointer-events: auto;
}
Fügen wir einfach eine coole Übergangsanimation für die Opazität hinzu und wir haben eine fertige Komponente
Es ist wahrscheinlich noch cooler, wenn wir mehr Kacheln hinzufügen und ein zweidimensionales Layout erstellen
Das endgültige CSS sieht so aus
.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;
}
Mit nur 2 zusätzlichen Codezeilen haben wir das Lückenproblem gelöst!
Mögliche Probleme
Obwohl es eine kompakte Lösung ist, gibt es einige Situationen, in denen sie möglicherweise einige Workarounds erfordert.
Leider funktioniert dieser Trick nicht, wenn der Container scrollbar sein soll, z. B. in einer Art horizontalem Slider. Der Stil pointer-events: none würde nicht nur das Hover-Ereignis, sondern auch alle anderen ignorieren. In solchen Fällen können Sie den .grid in einen anderen Container einpacken, so
<div class="container">
<ul class="grid">
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
<li class="grid__child"></li>
</ul>
</div>
Zusammenfassung
Ich ermutige Sie dringend, zu experimentieren und zu versuchen, einen einfacheren und nativeren Ansatz für Aufgaben zu finden, die normalerweise ein gewisses Maß an Komplexität erwarten lassen. Webtechnologien wie CSS werden immer leistungsfähiger und durch die Verwendung nativer Standardlösungen können Sie großartige Ergebnisse erzielen, ohne Ihren Code warten und ihn an Browserhersteller abgeben zu müssen.
Ich hoffe, Ihnen hat dieses kurze Tutorial gefallen und Sie fanden es nützlich. Danke!
Der Autor wählte den Tech Education Fund aus, um im Rahmen des Write for DOnations-Programms eine Spende zu erhalten.
Auf Twitter empfiehlt KonstantinRouda (Konrud),
:has()zu verwenden, um die Notwendigkeit vonpointer-events: nonezu umgehen.Cool, danke fürs Teilen hier!
Besserer Trick mit Sichtbarkeit und besserer Browserkompatibilität -> https://jsbin.com/hinikinete/2/edit?html,css,output