You've probably seen this effect before — you hover over one card, and all the other cards fade out a little, making the hovered one stand out.
Before hover: While hovering card B:
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ A │ │ B │ │ C │ │ A │ │ B │ │ C │
└──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘
100% 100% 100% dim bright dim
It's clean, it draws attention to the right place, and it takes about 5 lines of CSS.
The HTML
Nothing special here — a wrapper div and some cards inside it.
<div class="cards">
<div class="card">Card A</div>
<div class="card">Card B</div>
<div class="card">Card C</div>
</div>
The CSS
.cards:has(.card:hover) .card:not(:hover) {
opacity: 0.5;
}
That's it. Let's break it down:
-
.cards:has(.card:hover)— targets the wrapper when any card inside it is being hovered -
.card:not(:hover)— selects all cards except the one being hovered -
opacity: 0.5— dims them
So in plain English: "If something inside .cards is hovered, dim every .card that isn't the hovered one."
Add a smooth transition
The snap between full and dimmed opacity can feel abrupt. Add a transition to the cards:
.card {
transition: opacity 0.3s ease;
}
.cards:has(.card:hover) .card:not(:hover) {
opacity: 0.5;
}
Now it fades in and out smoothly.
Works across columns too
This approach works even when your cards are split across multiple columns (like a masonry layout), because the selector targets by class anywhere inside the wrapper — not just direct children.
<div class="cards">
<div class="column">
<div class="card">Card A</div>
<div class="card">Card C</div>
</div>
<div class="column">
<div class="card">Card B</div>
<div class="card">Card D</div>
</div>
</div>
The same CSS still works — hover card A, and B, C, D all dim regardless of which column they're in.
Browser support
The :has() selector is supported in all modern browsers. Just keep in mind it doesn't work in Firefox versions before 121 or older browsers, so add a graceful fallback if you need wide coverage (e.g. just skip the effect entirely for those browsers — it's purely visual).
Simple, no JavaScript, no extra libraries. Just CSS doing what it's good at.
Top comments (0)