20 CSS Image Hover Effects 04 / 20
CSS Grid Image Blur Overlay Text Hover
Visually soft hover where the background image blurs under a dark overlay via backdrop-filter to make typography legible.
The code
<div class="ih-04">
<div class="ih-04__grid">
<div class="ih-04__card">
<div class="ih-04__bg ih-04__bg--1"></div>
<span class="ih-04__emoji">🌌</span>
<div class="ih-04__overlay">
<p class="ih-04__cat">Editorial</p>
<p class="ih-04__title">The Infinite Canvas</p>
<p class="ih-04__desc">Exploring the boundaries of digital art in 2025</p>
</div>
</div>
<div class="ih-04__card">
<div class="ih-04__bg ih-04__bg--2"></div>
<span class="ih-04__emoji">🌿</span>
<div class="ih-04__overlay">
<p class="ih-04__cat">Nature</p>
<p class="ih-04__title">Bioluminescent Depths</p>
<p class="ih-04__desc">Life thriving in the ocean's twilight zone</p>
</div>
</div>
<div class="ih-04__card">
<div class="ih-04__bg ih-04__bg--3"></div>
<span class="ih-04__emoji">✨</span>
<div class="ih-04__overlay">
<p class="ih-04__cat">Culture</p>
<p class="ih-04__title">Neon Flux Collection</p>
<p class="ih-04__desc">Street art meets future-forward design aesthetics</p>
</div>
</div>
</div>
</div> <div class="ih-04">
<div class="ih-04__grid">
<div class="ih-04__card">
<div class="ih-04__bg ih-04__bg--1"></div>
<span class="ih-04__emoji">🌌</span>
<div class="ih-04__overlay">
<p class="ih-04__cat">Editorial</p>
<p class="ih-04__title">The Infinite Canvas</p>
<p class="ih-04__desc">Exploring the boundaries of digital art in 2025</p>
</div>
</div>
<div class="ih-04__card">
<div class="ih-04__bg ih-04__bg--2"></div>
<span class="ih-04__emoji">🌿</span>
<div class="ih-04__overlay">
<p class="ih-04__cat">Nature</p>
<p class="ih-04__title">Bioluminescent Depths</p>
<p class="ih-04__desc">Life thriving in the ocean's twilight zone</p>
</div>
</div>
<div class="ih-04__card">
<div class="ih-04__bg ih-04__bg--3"></div>
<span class="ih-04__emoji">✨</span>
<div class="ih-04__overlay">
<p class="ih-04__cat">Culture</p>
<p class="ih-04__title">Neon Flux Collection</p>
<p class="ih-04__desc">Street art meets future-forward design aesthetics</p>
</div>
</div>
</div>
</div>.ih-04, .ih-04 *, .ih-04 *::before, .ih-04 *::after { margin:0;padding:0;box-sizing:border-box; }
.ih-04 ::selection { background:#8b5cf6;color:#fff; }
.ih-04 {
--accent:#8b5cf6; --bg:#080810; --text:#f1f5f9; --muted:#94a3b8;
--duration:0.4s; --ease:cubic-bezier(0.25,0.46,0.45,0.94);
font-family:system-ui,sans-serif; background:var(--bg); padding:40px 24px;
min-height: 100vh; display:flex; align-items:center; justify-content:center;
}
.ih-04__grid { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; max-width:780px; width:100%; }
.ih-04__card { position:relative; border-radius:14px; overflow:hidden; aspect-ratio:3/4; cursor:pointer; }
.ih-04__bg { position:absolute; inset:0; transition:filter var(--duration) var(--ease), transform var(--duration) var(--ease); }
.ih-04__bg--1 { background:linear-gradient(135deg,#0f0c29,#302b63,#24243e); }
.ih-04__bg--2 { background:linear-gradient(135deg,#0a3d2e,#155e43,#6ee7b7); }
.ih-04__bg--3 { background:linear-gradient(135deg,#1a0010,#6b1d4e,#e879f9); }
.ih-04__emoji { position:absolute; top:50%; left:50%; transform:translate(-50%,-60%); font-size:60px; opacity:0.35; transition:opacity var(--duration) var(--ease), transform var(--duration) var(--ease); }
/* backdrop-filter blur on overlay — applied to the ::before pseudo so it blurs the sibling bg */
.ih-04__overlay {
position:absolute; inset:0;
background:rgba(0,0,0,0);
/* We use backdrop-filter on the overlay itself */
backdrop-filter:blur(0px) brightness(1);
-webkit-backdrop-filter:blur(0px) brightness(1);
transition:backdrop-filter var(--duration) var(--ease),
-webkit-backdrop-filter var(--duration) var(--ease),
background var(--duration) var(--ease);
display:flex; flex-direction:column; justify-content:flex-end; padding:20px;
}
.ih-04__card:hover .ih-04__bg { transform:scale(1.05); }
.ih-04__card:hover .ih-04__emoji { opacity:0.08; transform:translate(-50%,-60%) scale(1.2); }
.ih-04__card:hover .ih-04__overlay {
backdrop-filter:blur(8px) brightness(0.6);
-webkit-backdrop-filter:blur(8px) brightness(0.6);
background:rgba(0,0,0,0.15);
}
.ih-04__cat { font-size:10px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; color:var(--accent); margin-bottom:6px; opacity:0; transform:translateY(10px); transition:opacity var(--duration) var(--ease), transform var(--duration) var(--ease); }
.ih-04__title { font-size:15px; font-weight:700; color:var(--text); line-height:1.3; opacity:0; transform:translateY(12px); transition:opacity calc(var(--duration)*1.1) var(--ease), transform calc(var(--duration)*1.1) var(--ease); }
.ih-04__desc { font-size:11px; color:var(--muted); margin-top:5px; opacity:0; transform:translateY(14px); transition:opacity calc(var(--duration)*1.2) var(--ease), transform calc(var(--duration)*1.2) var(--ease); }
.ih-04__card:hover .ih-04__cat, .ih-04__card:hover .ih-04__title, .ih-04__card:hover .ih-04__desc { opacity:1; transform:none; }
@media (prefers-reduced-motion:reduce) {
.ih-04__bg,.ih-04__overlay,.ih-04__cat,.ih-04__title,.ih-04__desc,.ih-04__emoji { transition:none; }
.ih-04__overlay { backdrop-filter:blur(8px) brightness(0.6); }
.ih-04__cat,.ih-04__title,.ih-04__desc { opacity:1; transform:none; }
} .ih-04, .ih-04 *, .ih-04 *::before, .ih-04 *::after { margin:0;padding:0;box-sizing:border-box; }
.ih-04 ::selection { background:#8b5cf6;color:#fff; }
.ih-04 {
--accent:#8b5cf6; --bg:#080810; --text:#f1f5f9; --muted:#94a3b8;
--duration:0.4s; --ease:cubic-bezier(0.25,0.46,0.45,0.94);
font-family:system-ui,sans-serif; background:var(--bg); padding:40px 24px;
min-height: 100vh; display:flex; align-items:center; justify-content:center;
}
.ih-04__grid { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; max-width:780px; width:100%; }
.ih-04__card { position:relative; border-radius:14px; overflow:hidden; aspect-ratio:3/4; cursor:pointer; }
.ih-04__bg { position:absolute; inset:0; transition:filter var(--duration) var(--ease), transform var(--duration) var(--ease); }
.ih-04__bg--1 { background:linear-gradient(135deg,#0f0c29,#302b63,#24243e); }
.ih-04__bg--2 { background:linear-gradient(135deg,#0a3d2e,#155e43,#6ee7b7); }
.ih-04__bg--3 { background:linear-gradient(135deg,#1a0010,#6b1d4e,#e879f9); }
.ih-04__emoji { position:absolute; top:50%; left:50%; transform:translate(-50%,-60%); font-size:60px; opacity:0.35; transition:opacity var(--duration) var(--ease), transform var(--duration) var(--ease); }
/* backdrop-filter blur on overlay — applied to the ::before pseudo so it blurs the sibling bg */
.ih-04__overlay {
position:absolute; inset:0;
background:rgba(0,0,0,0);
/* We use backdrop-filter on the overlay itself */
backdrop-filter:blur(0px) brightness(1);
-webkit-backdrop-filter:blur(0px) brightness(1);
transition:backdrop-filter var(--duration) var(--ease),
-webkit-backdrop-filter var(--duration) var(--ease),
background var(--duration) var(--ease);
display:flex; flex-direction:column; justify-content:flex-end; padding:20px;
}
.ih-04__card:hover .ih-04__bg { transform:scale(1.05); }
.ih-04__card:hover .ih-04__emoji { opacity:0.08; transform:translate(-50%,-60%) scale(1.2); }
.ih-04__card:hover .ih-04__overlay {
backdrop-filter:blur(8px) brightness(0.6);
-webkit-backdrop-filter:blur(8px) brightness(0.6);
background:rgba(0,0,0,0.15);
}
.ih-04__cat { font-size:10px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; color:var(--accent); margin-bottom:6px; opacity:0; transform:translateY(10px); transition:opacity var(--duration) var(--ease), transform var(--duration) var(--ease); }
.ih-04__title { font-size:15px; font-weight:700; color:var(--text); line-height:1.3; opacity:0; transform:translateY(12px); transition:opacity calc(var(--duration)*1.1) var(--ease), transform calc(var(--duration)*1.1) var(--ease); }
.ih-04__desc { font-size:11px; color:var(--muted); margin-top:5px; opacity:0; transform:translateY(14px); transition:opacity calc(var(--duration)*1.2) var(--ease), transform calc(var(--duration)*1.2) var(--ease); }
.ih-04__card:hover .ih-04__cat, .ih-04__card:hover .ih-04__title, .ih-04__card:hover .ih-04__desc { opacity:1; transform:none; }
@media (prefers-reduced-motion:reduce) {
.ih-04__bg,.ih-04__overlay,.ih-04__cat,.ih-04__title,.ih-04__desc,.ih-04__emoji { transition:none; }
.ih-04__overlay { backdrop-filter:blur(8px) brightness(0.6); }
.ih-04__cat,.ih-04__title,.ih-04__desc { opacity:1; transform:none; }
}How this works
backdrop-filter: blur(8px) brightness(0.6) is applied to the overlay element rather than the image itself. This means the blur composites against everything rendered behind the overlay — the image, any gradients, any decorative shapes. On hover, both the blur and brightness values animate from zero using a transition on the backdrop-filter shorthand.
Text children of the overlay start hidden with opacity: 0; transform: translateY(10px) and enter on hover, staggered via duration multipliers. The image simultaneously scales up slightly with transform: scale(1.05) to reinforce that it is "active", while the blur softens it visually to push it to the background.
Customize
- Increase the blur radius to
blur(16px)for a more opaque frosted-glass feel, or drop it toblur(4px)for a subtle soft-focus effect. - Tint the overlay with a brand colour:
background: rgba(124, 58, 237, 0.15)gives a violet wash while still showing the image beneath. - Add
saturate(0.5)to thebackdrop-filterstack to desaturate the image as it blurs:backdrop-filter: blur(8px) brightness(0.6) saturate(0.5). - For cards with bright images, increase the brightness reduction:
brightness(0.45)ensures white text remains AA contrast-compliant. - Combine with a
mix-blend-mode: multiplyon the overlay background for more aggressive colour grading effects.
Watch out for
backdrop-filterdoes NOT work on elements that are siblings of the blurred content — it only blurs what is visually behind it in the stacking order. The overlay must be a child or sibling sitting on top of the image layer.- Safari requires the
-webkit-backdrop-filtervendor prefix in addition to the unprefixed version — always include both. - Animating
backdrop-filtercan cause significant GPU memory usage when many cards are visible simultaneously — consider applying only within a visible viewport via IntersectionObserver.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 76+ | 9+ (prefixed) | 103+ | 76+ |
Firefox added backdrop-filter support in v103 without a flag; older Firefox versions will see the text overlay without blur.