Responsive CSS Framework for Image Cards
Create responsive image cards with CSS grid layout and hover effects, perfect for galleries.
Code
/* Responsive Image Card Grid (Gallery) — production-ready CSS.
Drop in: wrap cards in .c-card-grid; each card uses .c-card + .c-card__media + .c-card__content. */
:root {
--card-min: 250px;
--gap: 16px;
--radius: 12px;
--shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
--overlay: rgba(0, 0, 0, 0.55);
--text: #fff;
--ease: cubic-bezier(.2, .8, .2, 1);
--dur: 220ms;
}
.c-card-grid {
/* Fallback for older browsers: flex grid */
display: flex;
flex-wrap: wrap;
gap: var(--gap);
}
/* Prefer CSS Grid when supported for better packing/consistency */
@supports (display: grid) {
.c-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(var(--card-min), 1fr));
gap: var(--gap);
}
}
.c-card {
position: relative;
overflow: hidden;
border-radius: var(--radius);
background: #111; /* Prevents flash while image loads */
box-shadow: var(--shadow);
/* GPU-friendly: transform/opacity only for hover */
transition: transform var(--dur) var(--ease);
will-change: transform; /* Performance hint for hover-heavy galleries */
}
/* Flex fallback: approximate grid columns without expensive selectors */
.c-card-grid > .c-card {
flex: 1 1 var(--card-min);
min-width: var(--card-min);
}
.c-card:focus-within,
.c-card:hover {
transform: translateY(-2px) scale(1.03);
}
.c-card__media {
display: block;
width: 100%;
aspect-ratio: 4 / 3; /* Keeps layout stable; prevents CLS */
object-fit: cover;
}
/* Fallback for browsers without aspect-ratio support */
@supports not (aspect-ratio: 1) {
.c-card__media {
height: 220px;
}
}
.c-card__content {
position: absolute;
inset: auto 0 0 0;
padding: 12px 14px;
color: var(--text);
background: linear-gradient(to top, var(--overlay), rgba(0, 0, 0, 0));
opacity: 0;
transform: translateY(6px);
transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.c-card:focus-within .c-card__content,
.c-card:hover .c-card__content {
opacity: 1;
transform: translateY(0);
}
/* Accessibility: respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
.c-card,
.c-card__content {
transition: none;
}
}
/* Small screens: slightly smaller minimum card width for denser galleries */
@media (max-width: 480px) {
:root { --card-min: 200px; }
}
/* Example usage:
<div class="c-card-grid">
<article class="c-card">
<img class="c-card__media" src="image.jpg" alt="Project preview">
<div class="c-card__content">Project Title</div>
</article>
</div>
*/