05 / 20
All 20 in 20 CSS Image Hover Effects
- 01CSS Image Hover Zoom In Card
- 02CSS Hover Reveal Text Over Image
- 03E-Commerce Product Image Swap on Hover
- 04CSS Grid Image Blur Overlay Text Hover
- 05CSS Card Slide Up Caption on Hover
- 06CSS Grayscale to Color Image Hover
- 07CSS Image Color Overlay Tint on Hover
- 08Neumorphic Image Card Hover Effect CSS
- 09Glassmorphism Overlay on Image Hover
- 10CSS Glowing Neon Border Image Hover
- 11CSS Image Clip-Path Transition Hover
- 12CSS Image Tilt 3D Perspective Hover
- 13CSS Shining Light Glare Image Hover
- 14CSS Image Split Transition Hover
- 15CSS Image Ripple Animation Hover
- 16Circular Team Profile Avatar Hover CSS
- 17CSS Fullscreen Background Image Hover
- 18CSS Masonry Gallery Zoom Hover
- 19CSS Image Icon Reveal Center Hover
- 20CSS Image Card Flip 3D Animation Hover
CSS Card Slide Up Caption on Hover
A caption panel anchored at the bottom that slides up into view from below the image frame, revealing metadata and a category pill.
Build UI like this from scratch: Flexbox, Grid, animations & responsive CSS
ZTM · The CSS Bootcamp · 30‑day money-back guarantee · Affiliate link
The code
<div class="ih-05">
<div class="ih-05__grid">
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--1"><span class="ih-05__icon">🎵</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Synthwave</div>
<p class="ih-05__title">Neon Highways</p>
<p class="ih-05__meta">A 12-track journey through retro-futuristic soundscapes and pulsing basslines</p>
<span class="ih-05__pill">New Album</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--2"><span class="ih-05__icon">🌊</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Ambient</div>
<p class="ih-05__title">Ocean Mind</p>
<p class="ih-05__meta">Meditative binaural compositions recorded at the Faroe Islands coastline</p>
<span class="ih-05__pill">EP Release</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--3"><span class="ih-05__icon">🔮</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Electronic</div>
<p class="ih-05__title">Violet Frequencies</p>
<p class="ih-05__meta">Experimental club music blending modular synthesis and jazz improvisation</p>
<span class="ih-05__pill">Single</span>
</div>
</div>
</div>
</div><div class="ih-05">
<div class="ih-05__grid">
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--1"><span class="ih-05__icon">🎵</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Synthwave</div>
<p class="ih-05__title">Neon Highways</p>
<p class="ih-05__meta">A 12-track journey through retro-futuristic soundscapes and pulsing basslines</p>
<span class="ih-05__pill">New Album</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--2"><span class="ih-05__icon">🌊</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Ambient</div>
<p class="ih-05__title">Ocean Mind</p>
<p class="ih-05__meta">Meditative binaural compositions recorded at the Faroe Islands coastline</p>
<span class="ih-05__pill">EP Release</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--3"><span class="ih-05__icon">🔮</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Electronic</div>
<p class="ih-05__title">Violet Frequencies</p>
<p class="ih-05__meta">Experimental club music blending modular synthesis and jazz improvisation</p>
<span class="ih-05__pill">Single</span>
</div>
</div>
</div>
</div>.ih-05,
.ih-05 *,
.ih-05 *::before,
.ih-05 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.ih-05 ::selection {
background: #f472b6;
color: #000;
}
.ih-05 {
--accent: #f472b6;
--accent2: #818cf8;
--bg: #0a0a10;
--card: #141420;
--text: #f1f5f9;
--muted: #64748b;
--duration: 0.4s;
--ease: cubic-bezier(0.16,1,0.3,1);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 40px 24px;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.ih-05__grid {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 16px;
max-width: 780px;
width: 100%;
}
.ih-05__card {
position: relative;
border-radius: 12px;
overflow: hidden;
aspect-ratio: 4/5;
cursor: pointer;
background: var(--card);
border: 1px solid rgba(255,255,255,0.05);
}
.ih-05__img {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
transition: transform var(--duration) var(--ease);
}
.ih-05__img--1 {
background: linear-gradient(150deg,#0d0d1a 0%,#1e1b4b 60%,#312e81 100%);
}
.ih-05__img--2 {
background: linear-gradient(150deg,#042f2e 0%,#0f766e 60%,#2dd4bf 100%);
}
.ih-05__img--3 {
background: linear-gradient(150deg,#1a0626 0%,#6b21a8 60%,#c084fc 100%);
}
.ih-05__card:hover .ih-05__img {
transform: scale(1.06) translateY(-4px);
}
.ih-05__icon {
font-size: 56px;
opacity: 0.35;
transition: opacity var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__icon {
opacity: 0.12;
}
/* The caption panel slides up from the bottom */
.ih-05__caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.7) 60%, transparent 100%);
padding: 40px 16px 16px;
transform: translateY(calc(100% - 44px));
transition: transform var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__caption {
transform: translateY(0);
}
.ih-05__peek {
font-size: 12px;
font-weight: 600;
color: var(--text);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.ih-05__dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
flex-shrink: 0;
}
.ih-05__title {
font-size: 14px;
font-weight: 700;
color: var(--text);
margin-bottom: 6px;
}
.ih-05__meta {
font-size: 11px;
color: var(--muted);
line-height: 1.5;
}
.ih-05__pill {
display: inline-block;
margin-top: 8px;
padding: 3px 8px;
border-radius: 20px;
background: rgba(244,114,182,0.15);
border: 1px solid rgba(244,114,182,0.3);
font-size: 10px;
font-weight: 700;
color: var(--accent);
letter-spacing: 0.06em;
}
@media (prefers-reduced-motion: reduce) {
.ih-05__img,
.ih-05__icon,
.ih-05__caption {
transition: none;
}
.ih-05__caption {
transform: none;
}
}.ih-05,
.ih-05 *,
.ih-05 *::before,
.ih-05 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.ih-05 ::selection {
background: #f472b6;
color: #000;
}
.ih-05 {
--accent: #f472b6;
--accent2: #818cf8;
--bg: #0a0a10;
--card: #141420;
--text: #f1f5f9;
--muted: #64748b;
--duration: 0.4s;
--ease: cubic-bezier(0.16,1,0.3,1);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 40px 24px;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.ih-05__grid {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 16px;
max-width: 780px;
width: 100%;
}
.ih-05__card {
position: relative;
border-radius: 12px;
overflow: hidden;
aspect-ratio: 4/5;
cursor: pointer;
background: var(--card);
border: 1px solid rgba(255,255,255,0.05);
}
.ih-05__img {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
transition: transform var(--duration) var(--ease);
}
.ih-05__img--1 {
background: linear-gradient(150deg,#0d0d1a 0%,#1e1b4b 60%,#312e81 100%);
}
.ih-05__img--2 {
background: linear-gradient(150deg,#042f2e 0%,#0f766e 60%,#2dd4bf 100%);
}
.ih-05__img--3 {
background: linear-gradient(150deg,#1a0626 0%,#6b21a8 60%,#c084fc 100%);
}
.ih-05__card:hover .ih-05__img {
transform: scale(1.06) translateY(-4px);
}
.ih-05__icon {
font-size: 56px;
opacity: 0.35;
transition: opacity var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__icon {
opacity: 0.12;
}
/* The caption panel slides up from the bottom */
.ih-05__caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.7) 60%, transparent 100%);
padding: 40px 16px 16px;
transform: translateY(calc(100% - 44px));
transition: transform var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__caption {
transform: translateY(0);
}
.ih-05__peek {
font-size: 12px;
font-weight: 600;
color: var(--text);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.ih-05__dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
flex-shrink: 0;
}
.ih-05__title {
font-size: 14px;
font-weight: 700;
color: var(--text);
margin-bottom: 6px;
}
.ih-05__meta {
font-size: 11px;
color: var(--muted);
line-height: 1.5;
}
.ih-05__pill {
display: inline-block;
margin-top: 8px;
padding: 3px 8px;
border-radius: 20px;
background: rgba(244,114,182,0.15);
border: 1px solid rgba(244,114,182,0.3);
font-size: 10px;
font-weight: 700;
color: var(--accent);
letter-spacing: 0.06em;
}
@media (prefers-reduced-motion: reduce) {
.ih-05__img,
.ih-05__icon,
.ih-05__caption {
transition: none;
}
.ih-05__caption {
transform: none;
}
}Here's a working CSS Image Hover Effect from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Card Slide Up Caption on Hover
Source: https://codefronts.com/motion/css-image-hover-effects/css-card-slide-up-caption-on-hover/
A caption panel anchored at the bottom that slides up into view from below the image frame, revealing metadata and a category pill.
## HTML
```html
<div class="ih-05">
<div class="ih-05__grid">
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--1"><span class="ih-05__icon">🎵</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Synthwave</div>
<p class="ih-05__title">Neon Highways</p>
<p class="ih-05__meta">A 12-track journey through retro-futuristic soundscapes and pulsing basslines</p>
<span class="ih-05__pill">New Album</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--2"><span class="ih-05__icon">🌊</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Ambient</div>
<p class="ih-05__title">Ocean Mind</p>
<p class="ih-05__meta">Meditative binaural compositions recorded at the Faroe Islands coastline</p>
<span class="ih-05__pill">EP Release</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--3"><span class="ih-05__icon">🔮</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Electronic</div>
<p class="ih-05__title">Violet Frequencies</p>
<p class="ih-05__meta">Experimental club music blending modular synthesis and jazz improvisation</p>
<span class="ih-05__pill">Single</span>
</div>
</div>
</div>
</div>
```
## CSS
```css
.ih-05,
.ih-05 *,
.ih-05 *::before,
.ih-05 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.ih-05 ::selection {
background: #f472b6;
color: #000;
}
.ih-05 {
--accent: #f472b6;
--accent2: #818cf8;
--bg: #0a0a10;
--card: #141420;
--text: #f1f5f9;
--muted: #64748b;
--duration: 0.4s;
--ease: cubic-bezier(0.16,1,0.3,1);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 40px 24px;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.ih-05__grid {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 16px;
max-width: 780px;
width: 100%;
}
.ih-05__card {
position: relative;
border-radius: 12px;
overflow: hidden;
aspect-ratio: 4/5;
cursor: pointer;
background: var(--card);
border: 1px solid rgba(255,255,255,0.05);
}
.ih-05__img {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
transition: transform var(--duration) var(--ease);
}
.ih-05__img--1 {
background: linear-gradient(150deg,#0d0d1a 0%,#1e1b4b 60%,#312e81 100%);
}
.ih-05__img--2 {
background: linear-gradient(150deg,#042f2e 0%,#0f766e 60%,#2dd4bf 100%);
}
.ih-05__img--3 {
background: linear-gradient(150deg,#1a0626 0%,#6b21a8 60%,#c084fc 100%);
}
.ih-05__card:hover .ih-05__img {
transform: scale(1.06) translateY(-4px);
}
.ih-05__icon {
font-size: 56px;
opacity: 0.35;
transition: opacity var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__icon {
opacity: 0.12;
}
/* The caption panel slides up from the bottom */
.ih-05__caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.7) 60%, transparent 100%);
padding: 40px 16px 16px;
transform: translateY(calc(100% - 44px));
transition: transform var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__caption {
transform: translateY(0);
}
.ih-05__peek {
font-size: 12px;
font-weight: 600;
color: var(--text);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.ih-05__dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
flex-shrink: 0;
}
.ih-05__title {
font-size: 14px;
font-weight: 700;
color: var(--text);
margin-bottom: 6px;
}
.ih-05__meta {
font-size: 11px;
color: var(--muted);
line-height: 1.5;
}
.ih-05__pill {
display: inline-block;
margin-top: 8px;
padding: 3px 8px;
border-radius: 20px;
background: rgba(244,114,182,0.15);
border: 1px solid rgba(244,114,182,0.3);
font-size: 10px;
font-weight: 700;
color: var(--accent);
letter-spacing: 0.06em;
}
@media (prefers-reduced-motion: reduce) {
.ih-05__img,
.ih-05__icon,
.ih-05__caption {
transition: none;
}
.ih-05__caption {
transform: none;
}
}
```Here's a working CSS Image Hover Effect from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Card Slide Up Caption on Hover
Source: https://codefronts.com/motion/css-image-hover-effects/css-card-slide-up-caption-on-hover/
A caption panel anchored at the bottom that slides up into view from below the image frame, revealing metadata and a category pill.
## HTML
```html
<div class="ih-05">
<div class="ih-05__grid">
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--1"><span class="ih-05__icon">🎵</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Synthwave</div>
<p class="ih-05__title">Neon Highways</p>
<p class="ih-05__meta">A 12-track journey through retro-futuristic soundscapes and pulsing basslines</p>
<span class="ih-05__pill">New Album</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--2"><span class="ih-05__icon">🌊</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Ambient</div>
<p class="ih-05__title">Ocean Mind</p>
<p class="ih-05__meta">Meditative binaural compositions recorded at the Faroe Islands coastline</p>
<span class="ih-05__pill">EP Release</span>
</div>
</div>
<div class="ih-05__card">
<div class="ih-05__img ih-05__img--3"><span class="ih-05__icon">🔮</span></div>
<div class="ih-05__caption">
<div class="ih-05__peek"><span class="ih-05__dot"></span>Electronic</div>
<p class="ih-05__title">Violet Frequencies</p>
<p class="ih-05__meta">Experimental club music blending modular synthesis and jazz improvisation</p>
<span class="ih-05__pill">Single</span>
</div>
</div>
</div>
</div>
```
## CSS
```css
.ih-05,
.ih-05 *,
.ih-05 *::before,
.ih-05 *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.ih-05 ::selection {
background: #f472b6;
color: #000;
}
.ih-05 {
--accent: #f472b6;
--accent2: #818cf8;
--bg: #0a0a10;
--card: #141420;
--text: #f1f5f9;
--muted: #64748b;
--duration: 0.4s;
--ease: cubic-bezier(0.16,1,0.3,1);
font-family: system-ui,sans-serif;
background: var(--bg);
padding: 40px 24px;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.ih-05__grid {
display: grid;
grid-template-columns: repeat(3,1fr);
gap: 16px;
max-width: 780px;
width: 100%;
}
.ih-05__card {
position: relative;
border-radius: 12px;
overflow: hidden;
aspect-ratio: 4/5;
cursor: pointer;
background: var(--card);
border: 1px solid rgba(255,255,255,0.05);
}
.ih-05__img {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
transition: transform var(--duration) var(--ease);
}
.ih-05__img--1 {
background: linear-gradient(150deg,#0d0d1a 0%,#1e1b4b 60%,#312e81 100%);
}
.ih-05__img--2 {
background: linear-gradient(150deg,#042f2e 0%,#0f766e 60%,#2dd4bf 100%);
}
.ih-05__img--3 {
background: linear-gradient(150deg,#1a0626 0%,#6b21a8 60%,#c084fc 100%);
}
.ih-05__card:hover .ih-05__img {
transform: scale(1.06) translateY(-4px);
}
.ih-05__icon {
font-size: 56px;
opacity: 0.35;
transition: opacity var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__icon {
opacity: 0.12;
}
/* The caption panel slides up from the bottom */
.ih-05__caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(to top, rgba(0,0,0,0.92) 0%, rgba(0,0,0,0.7) 60%, transparent 100%);
padding: 40px 16px 16px;
transform: translateY(calc(100% - 44px));
transition: transform var(--duration) var(--ease);
}
.ih-05__card:hover .ih-05__caption {
transform: translateY(0);
}
.ih-05__peek {
font-size: 12px;
font-weight: 600;
color: var(--text);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.ih-05__dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent);
flex-shrink: 0;
}
.ih-05__title {
font-size: 14px;
font-weight: 700;
color: var(--text);
margin-bottom: 6px;
}
.ih-05__meta {
font-size: 11px;
color: var(--muted);
line-height: 1.5;
}
.ih-05__pill {
display: inline-block;
margin-top: 8px;
padding: 3px 8px;
border-radius: 20px;
background: rgba(244,114,182,0.15);
border: 1px solid rgba(244,114,182,0.3);
font-size: 10px;
font-weight: 700;
color: var(--accent);
letter-spacing: 0.06em;
}
@media (prefers-reduced-motion: reduce) {
.ih-05__img,
.ih-05__icon,
.ih-05__caption {
transition: none;
}
.ih-05__caption {
transform: none;
}
}
```How this works
The caption wrapper uses position: absolute; bottom: 0 and begins with transform: translateY(calc(100% - 44px)) — this value ensures the top "peek" strip (containing the dot and category name) remains visible as a persistent visual hint. On hover, transform: translateY(0) slides the whole panel fully into view.
The calc() expression ties the resting offset to the height of the peek strip, so if that strip height changes (e.g. larger font), the math remains correct. A linear gradient on the caption background provides the smooth transition from solid to transparent so it never appears as a hard edge over the image.
Make it yours
- Tune the peek height by changing
44pxin thetranslateYcalc — the value should equal the height of the always-visible strip. - Replace the gradient background with
backdrop-filter: blur()for a glassmorphic caption panel on top of busy imagery. - Add a subtle
scale(1.03)to the image on hover to visually separate it from the rising panel. - For horizontal caption reveal, switch to
transform: translateX()and anchor the panel to the left or right edge instead of bottom. - Include a "tap to reveal" ARIA label (
aria-label="Show details") on the card for keyboard and screen reader users.
Gotchas — read before shipping
- The
calc(100% - 44px)technique relies on the caption being the same height at rest as when expanded — if content is dynamic, usemax-heighttransitions instead but note the easing will be linear. - Setting
overflow: hiddenon the card clips the sliding panel; ensure the card wrapper does not restrict the panel's travel path. - iOS Safari below 15.4 has a known bug where
transformon absolutely-positioned children inside an overflow:hidden parent flickers — adding-webkit-overflow-scrolling: touchon the card often resolves it.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 51+ | 9+ | 36+ | 51+ |
Uses only CSS transforms, opacity, and linear-gradient — all broadly supported with no prefixes required.