Stunning Image Card Reveal Effect
Create a visually engaging image card effect that reveals content on hover, enhancing user engagement.
Code
<!--
Stunning Image Card Reveal Effect
Hover/focus reveals overlay content; includes keyboard + reduced-motion support.
-->
<div class="cards" role="list">
<article class="card" role="listitem" tabindex="0" aria-label="View details: Aurora Peak Jacket">
<img src="https://images.unsplash.com/photo-1520975661595-6453be3f7070?auto=format&fit=crop&w=800&q=80" alt="Model wearing a jacket in the mountains" loading="lazy" decoding="async">
<div class="card-content" aria-hidden="true">
<h3>Aurora Peak Jacket</h3>
<p>Waterproof shell • 3-layer build • New season colorways.</p>
<a class="card-cta" href="#" aria-label="Shop Aurora Peak Jacket">Shop now</a>
</div>
</article>
</div>
<style>
:root { color-scheme: dark; }
.cards { display: grid; place-items: center; padding: 24px; }
.card {
position: relative; overflow: hidden; width: 300px; height: 400px; border-radius: 15px;
box-shadow: 0 4px 20px rgba(0,0,0,.2); transition: transform .3s;
background: #111; outline: none; /* prevent layout shift if image is slow */
}
.card img {
width: 100%; height: 100%; object-fit: cover; transform: scale(1);
transition: transform .5s; will-change: transform; /* perf: hint GPU compositing */
}
.card-content {
position: absolute; inset: auto 0 0 0;
background: linear-gradient(to top, rgba(0,0,0,.78), rgba(0,0,0,.25));
color: #fff; padding: 18px 20px; transform: translateY(100%);
transition: transform .3s; will-change: transform;
}
.card-content h3 { margin: 0 0 6px; font: 600 18px/1.2 system-ui, sans-serif; }
.card-content p { margin: 0 0 12px; opacity: .92; font: 400 14px/1.45 system-ui, sans-serif; }
.card-cta {
display: inline-flex; align-items: center; gap: 8px;
padding: 10px 12px; border-radius: 10px; text-decoration: none;
color: #0b0b0b; background: #fff; font: 600 13px system-ui, sans-serif;
}
/* Hover + keyboard parity */
.card:hover { transform: translateY(-2px); }
.card:hover img, .card:focus-visible img { transform: scale(1.1); }
.card:hover .card-content, .card:focus-visible .card-content { transform: translateY(0); }
.card:focus-visible { box-shadow: 0 0 0 3px rgba(255,255,255,.55), 0 8px 28px rgba(0,0,0,.35); }
/* Respect user preference to reduce motion */
@media (prefers-reduced-motion: reduce) {
.card, .card img, .card-content { transition: none; }
}
</style>
<script>
// Enable "Enter/Space to open" behavior for keyboard users; safe no-op if no link.
document.querySelectorAll(".card").forEach((card) => {
card.addEventListener("keydown", (event) => {
if (event.key !== "Enter" && event.key !== " ") return;
event.preventDefault();
const primaryLink = card.querySelector(".card-cta");
if (primaryLink?.href) primaryLink.click();
});
});
</script>
<!-- Example usage: Duplicate <article class="card"> blocks inside .cards for galleries/portfolios. -->