Open demo

CSS code

HTML
<section class="fx-gallery" aria-labelledby="fx-title">
  <div class="gh"><div><p class="gh-kicker">Hollis Garden Studio</p><h2 id="fx-title">Grown and made</h2></div><p class="gh-meta">6 photographs · hover or tab through them</p></div>
  <ul class="fx-grid" role="list">
    <li><a class="fx fx-zoom" href="https://images.unsplash.com/photo-1490750967868-88aa4486c946?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1490750967868-88aa4486c946?auto=format&fit=crop&w=640&h=800&q=70" width="640" height="800" loading="lazy" alt="Orange poppies against a clear blue sky"><span class="fx-cap"><strong>Orange poppies</strong><span>Cutting garden, May</span></span></a><p class="lbl fx-name">Zoom</p></li>
    <li><a class="fx fx-slide" href="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&w=640&h=800&q=70" width="640" height="800" loading="lazy" alt="Rows of small green seedlings in a black seed tray"><span class="fx-panel"><strong>Seed trays</strong><span>Greenhouse, March</span><span class="fx-more">Tomatoes and peppers, sown on the 4th and pricked out three weeks later.</span></span></a><p class="lbl fx-name">Slide-up caption</p></li>
    <li><a class="fx fx-grey" href="https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?auto=format&fit=crop&w=640&h=800&q=70" width="640" height="800" loading="lazy" alt="Red poppies growing through a field of pale grass"><span class="fx-cap"><strong>Field edge</strong><span>Lower meadow, June</span></span></a><p class="lbl fx-name">Greyscale to colour</p></li>
    <li><a class="fx fx-tint" href="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?auto=format&fit=crop&w=640&h=800&q=70" width="640" height="800" loading="lazy" alt="Three white ceramic bottles holding dried poppy seed heads against a dark grey wall"><span class="fx-view" aria-hidden="true">View series <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span><span class="fx-cap"><strong>Bottle vases</strong><span>Studio shelf</span></span></a><p class="lbl fx-name">Colour overlay</p></li>
    <li><a class="fx fx-frame" href="https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&w=640&h=800&q=70" width="640" height="800" loading="lazy" alt="Speckled stoneware cups in cream and tan glazes on a white shelf"><span class="fx-cap"><strong>Stoneware cups</strong><span>Spring firing</span></span></a><p class="lbl fx-name">Inset frame</p></li>
    <li><a class="fx fx-lift" href="https://images.unsplash.com/photo-1416879595882-3373a0480b5b?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1416879595882-3373a0480b5b?auto=format&fit=crop&w=640&h=800&q=70" width="640" height="800" loading="lazy" alt="A green trowel scooping dark compost beside a small pot"><span class="fx-cap"><strong>Potting on</strong><span>Bench work, April</span></span></a><p class="lbl fx-name">Lift and shadow</p></li>
  </ul>
</section>
CSS
/* Image hover effects: six photo tiles, one effect each. */
.gh{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:6px 24px;margin-bottom:20px}
.gh-kicker{font-size:.75rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#3f6b3a}
.gh h2{margin-top:4px;font-size:1.75rem;line-height:1.15;letter-spacing:-.02em}
.gh-meta{font-size:.9rem;color:#5b6355}
.fx-grid{list-style:none;display:grid;grid-template-columns:1fr;gap:28px 20px}
@media (min-width:576px){.fx-grid{grid-template-columns:repeat(2,1fr)}}
@media (min-width:992px){.fx-grid{grid-template-columns:repeat(3,1fr)}}
.fx-name{margin:12px 0 0}

/* Shared tile: a link to the full photo, so every effect also runs on keyboard focus */
.fx{--fx-accent:#3f6b3a;--fx-radius:14px;position:relative;display:block;aspect-ratio:4/5;border-radius:var(--fx-radius);overflow:hidden;background:#d8d5c8;color:#fff;text-decoration:none}
.fx img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s cubic-bezier(.2,.7,.2,1),filter .5s}
.fx:hover,.fx:focus-visible{color:#fff}
.fx:focus-visible{outline:3px solid var(--fx-accent);outline-offset:3px}
.fx-cap{position:absolute;left:0;right:0;bottom:0;display:flex;flex-direction:column;gap:2px;padding:48px 18px 16px;background:linear-gradient(to top,rgba(16,22,16,.82),rgba(16,22,16,0))}
.fx-cap strong,.fx-panel strong{font-size:1.05rem}
.fx-cap span,.fx-panel span{font-size:.82rem;color:#e6e9e1}

/* 1. Zoom */
.fx-zoom:hover img,.fx-zoom:focus-visible img{transform:scale(1.08)}

/* 2. Slide-up caption: the title peeks, the details slide up */
.fx-panel{position:absolute;left:0;right:0;bottom:0;display:flex;flex-direction:column;gap:2px;padding:16px 18px 18px;background:rgba(24,36,24,.9);
  transform:translateY(calc(100% - 68px));transition:transform .4s cubic-bezier(.2,.7,.2,1)}
.fx-panel .fx-more{margin-top:10px;font-size:.88rem;line-height:1.5;color:#e6e9e1;opacity:0;transition:opacity .3s}
.fx-slide:hover .fx-panel,.fx-slide:focus-visible .fx-panel{transform:none}
.fx-slide:hover .fx-more,.fx-slide:focus-visible .fx-more{opacity:1}

/* 3. Greyscale to colour */
.fx-grey img{filter:grayscale(1)}
.fx-grey:hover img,.fx-grey:focus-visible img{filter:none}

/* 4. Colour overlay */
.fx-tint::after{content:"";position:absolute;inset:0;background:rgba(43,78,40,.82);opacity:0;transition:opacity .35s}
.fx-view{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;gap:8px;font-weight:600;opacity:0;transform:translateY(8px);transition:opacity .35s,transform .35s}
.fx-view svg{width:18px;height:18px}
.fx-tint .fx-cap{z-index:1}
.fx-tint:hover::after,.fx-tint:focus-visible::after,.fx-tint:hover .fx-view,.fx-tint:focus-visible .fx-view{opacity:1;transform:none}

/* 5. Inset frame */
.fx-frame img{transform:scale(1.06)}
.fx-frame::after{content:"";position:absolute;inset:14px;border:2px solid rgba(255,255,255,.92);border-radius:8px;opacity:0;transform:scale(1.05);transition:opacity .35s,transform .35s}
.fx-frame:hover img,.fx-frame:focus-visible img{transform:none}
.fx-frame:hover::after,.fx-frame:focus-visible::after{opacity:1;transform:none}

/* 6. Lift and shadow */
.fx-lift{box-shadow:0 2px 6px rgba(31,42,31,.12);transition:transform .3s,box-shadow .3s}
.fx-lift:hover,.fx-lift:focus-visible{transform:translateY(-6px);box-shadow:0 22px 40px -12px rgba(31,42,31,.45)}

/* Touch screens have no hover: show the hidden parts */
@media (hover:none){.fx-panel{transform:none}.fx-panel .fx-more{opacity:1}}
@media (prefers-reduced-motion:reduce){.fx img,.fx-panel,.fx-panel .fx-more,.fx-tint::after,.fx-view,.fx-frame::after,.fx-lift{transition:none}
  .fx-zoom:hover img,.fx-zoom:focus-visible img,.fx-frame img,.fx-lift:hover,.fx-lift:focus-visible{transform:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<section class="fx-gallery" aria-labelledby="fx-title">
  <div class="gh d-flex flex-wrap align-items-end justify-content-between"><div><p class="gh-kicker">Hollis Garden Studio</p><h2 id="fx-title" class="gh-title">Grown and made</h2></div><p class="gh-meta">6 photographs · hover or tab through them</p></div>
  <div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 fx-row">
    <div class="col"><a class="fx fx-zoom" href="https://images.unsplash.com/photo-1490750967868-88aa4486c946?auto=format&fit=crop&w=2000&q=70"><span class="ratio d-block"><img src="https://images.unsplash.com/photo-1490750967868-88aa4486c946?auto=format&fit=crop&w=640&h=800&q=70" class="object-fit-cover" width="640" height="800" loading="lazy" alt="Orange poppies against a clear blue sky"></span><span class="fx-cap"><strong>Orange poppies</strong><span>Cutting garden, May</span></span></a><p class="lbl fx-name">Zoom</p></div>
    <div class="col"><a class="fx fx-slide" href="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&w=2000&q=70"><span class="ratio d-block"><img src="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&w=640&h=800&q=70" class="object-fit-cover" width="640" height="800" loading="lazy" alt="Rows of small green seedlings in a black seed tray"></span><span class="fx-panel"><strong>Seed trays</strong><span>Greenhouse, March</span><span class="fx-more">Tomatoes and peppers, sown on the 4th and pricked out three weeks later.</span></span></a><p class="lbl fx-name">Slide-up caption</p></div>
    <div class="col"><a class="fx fx-grey" href="https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?auto=format&fit=crop&w=2000&q=70"><span class="ratio d-block"><img src="https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?auto=format&fit=crop&w=640&h=800&q=70" class="object-fit-cover" width="640" height="800" loading="lazy" alt="Red poppies growing through a field of pale grass"></span><span class="fx-cap"><strong>Field edge</strong><span>Lower meadow, June</span></span></a><p class="lbl fx-name">Greyscale to colour</p></div>
    <div class="col"><a class="fx fx-tint" href="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?auto=format&fit=crop&w=2000&q=70"><span class="ratio d-block"><img src="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?auto=format&fit=crop&w=640&h=800&q=70" class="object-fit-cover" width="640" height="800" loading="lazy" alt="Three white ceramic bottles holding dried poppy seed heads against a dark grey wall"></span><span class="fx-view" aria-hidden="true">View series <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span><span class="fx-cap"><strong>Bottle vases</strong><span>Studio shelf</span></span></a><p class="lbl fx-name">Colour overlay</p></div>
    <div class="col"><a class="fx fx-frame" href="https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&w=2000&q=70"><span class="ratio d-block"><img src="https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&w=640&h=800&q=70" class="object-fit-cover" width="640" height="800" loading="lazy" alt="Speckled stoneware cups in cream and tan glazes on a white shelf"></span><span class="fx-cap"><strong>Stoneware cups</strong><span>Spring firing</span></span></a><p class="lbl fx-name">Inset frame</p></div>
    <div class="col"><a class="fx fx-lift" href="https://images.unsplash.com/photo-1416879595882-3373a0480b5b?auto=format&fit=crop&w=2000&q=70"><span class="ratio d-block"><img src="https://images.unsplash.com/photo-1416879595882-3373a0480b5b?auto=format&fit=crop&w=640&h=800&q=70" class="object-fit-cover" width="640" height="800" loading="lazy" alt="A green trowel scooping dark compost beside a small pot"></span><span class="fx-cap"><strong>Potting on</strong><span>Bench work, April</span></span></a><p class="lbl fx-name">Lift and shadow</p></div>
  </div>
</section>
CSS
/* Image hover effects on Bootstrap's grid (.row-cols-*) and .ratio (4:5). */
.gh{gap:6px 24px;margin-bottom:20px}
.gh-kicker{margin:0;font-size:.75rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:#3f6b3a}
.gh-title{margin:4px 0 0;font-size:1.75rem;font-weight:700;line-height:1.15;letter-spacing:-.02em}
.gh-meta{margin:0;font-size:.9rem;color:#5b6355}
.fx-row{--bs-gutter-x:20px;--bs-gutter-y:28px}
.fx .ratio{--bs-aspect-ratio:125%}
.fx-name{margin:12px 0 0}

/* Shared tile: a link to the full photo, so every effect also runs on keyboard focus */
.fx{--fx-accent:#3f6b3a;--fx-radius:14px;position:relative;display:block;border-radius:var(--fx-radius);overflow:hidden;background:#d8d5c8;color:#fff;text-decoration:none}
.fx img{transition:transform .6s cubic-bezier(.2,.7,.2,1),filter .5s}
.fx:hover,.fx:focus-visible{color:#fff}
.fx:focus-visible{outline:3px solid var(--fx-accent);outline-offset:3px}
.fx-cap{position:absolute;left:0;right:0;bottom:0;display:flex;flex-direction:column;gap:2px;padding:48px 18px 16px;background:linear-gradient(to top,rgba(16,22,16,.82),rgba(16,22,16,0))}
.fx-cap strong,.fx-panel strong{font-size:1.05rem}
.fx-cap span,.fx-panel span{font-size:.82rem;color:#e6e9e1}

/* 1. Zoom */
.fx-zoom:hover img,.fx-zoom:focus-visible img{transform:scale(1.08)}

/* 2. Slide-up caption: the title peeks, the details slide up */
.fx-panel{position:absolute;left:0;right:0;bottom:0;display:flex;flex-direction:column;gap:2px;padding:16px 18px 18px;background:rgba(24,36,24,.9);
  transform:translateY(calc(100% - 68px));transition:transform .4s cubic-bezier(.2,.7,.2,1)}
.fx-panel .fx-more{margin-top:10px;font-size:.88rem;line-height:1.5;color:#e6e9e1;opacity:0;transition:opacity .3s}
.fx-slide:hover .fx-panel,.fx-slide:focus-visible .fx-panel{transform:none}
.fx-slide:hover .fx-more,.fx-slide:focus-visible .fx-more{opacity:1}

/* 3. Greyscale to colour */
.fx-grey img{filter:grayscale(1)}
.fx-grey:hover img,.fx-grey:focus-visible img{filter:none}

/* 4. Colour overlay */
.fx-tint::after{content:"";position:absolute;inset:0;background:rgba(43,78,40,.82);opacity:0;transition:opacity .35s}
.fx-view{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;gap:8px;font-weight:600;opacity:0;transform:translateY(8px);transition:opacity .35s,transform .35s}
.fx-view svg{width:18px;height:18px}
.fx-tint .fx-cap{z-index:1}
.fx-tint:hover::after,.fx-tint:focus-visible::after,.fx-tint:hover .fx-view,.fx-tint:focus-visible .fx-view{opacity:1;transform:none}

/* 5. Inset frame */
.fx-frame img{transform:scale(1.06)}
.fx-frame::after{content:"";position:absolute;inset:14px;border:2px solid rgba(255,255,255,.92);border-radius:8px;opacity:0;transform:scale(1.05);transition:opacity .35s,transform .35s}
.fx-frame:hover img,.fx-frame:focus-visible img{transform:none}
.fx-frame:hover::after,.fx-frame:focus-visible::after{opacity:1;transform:none}

/* 6. Lift and shadow */
.fx-lift{box-shadow:0 2px 6px rgba(31,42,31,.12);transition:transform .3s,box-shadow .3s}
.fx-lift:hover,.fx-lift:focus-visible{transform:translateY(-6px);box-shadow:0 22px 40px -12px rgba(31,42,31,.45)}

/* Touch screens have no hover: show the hidden parts */
@media (hover:none){.fx-panel{transform:none}.fx-panel .fx-more{opacity:1}}
@media (prefers-reduced-motion:reduce){.fx img,.fx-panel,.fx-panel .fx-more,.fx-tint::after,.fx-view,.fx-frame::after,.fx-lift{transition:none}
  .fx-zoom:hover img,.fx-zoom:focus-visible img,.fx-frame img,.fx-lift:hover,.fx-lift:focus-visible{transform:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<section aria-labelledby="fx-title">
  <div class="mb-5 flex flex-wrap items-end justify-between gap-x-6 gap-y-1.5"><div><p class="text-xs leading-[normal] font-bold tracking-[.14em] text-[#3f6b3a] uppercase">Hollis Garden Studio</p><h2 id="fx-title" class="mt-1 text-[1.75rem] leading-[1.15] font-bold tracking-[-.02em]">Grown and made</h2></div><p class="text-[.9rem] leading-[normal] text-[#5b6355]">6 photographs · hover or tab through them</p></div>
  <ul class="grid grid-cols-1 gap-x-5 gap-y-7 min-[576px]:grid-cols-2 min-[992px]:grid-cols-3" role="list">
    <li><a class="group relative block aspect-[4/5] overflow-hidden rounded-[14px] bg-[#d8d5c8] text-white focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#3f6b3a]" href="https://images.unsplash.com/photo-1490750967868-88aa4486c946?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1490750967868-88aa4486c946?auto=format&fit=crop&w=640&h=800&q=70" class="block size-full object-cover transition-[scale,filter] duration-[600ms] ease-[cubic-bezier(.2,.7,.2,1)] motion-reduce:transition-none group-hover:scale-108 group-focus-visible:scale-108 motion-reduce:group-hover:scale-100 motion-reduce:group-focus-visible:scale-100" width="640" height="800" loading="lazy" alt="Orange poppies against a clear blue sky"><span class="absolute inset-x-0 bottom-0 flex flex-col gap-0.5 bg-linear-to-t from-[rgba(16,22,16,.82)] to-[rgba(16,22,16,0)] px-[18px] pt-12 pb-4"><strong class="text-[1.05rem]">Orange poppies</strong><span class="text-[.82rem] text-[#e6e9e1]">Cutting garden, May</span></span></a><p class="mt-3 block text-[.72rem] tracking-[.12em] text-[#5b6355] uppercase">Zoom</p></li>
    <li><a class="group relative block aspect-[4/5] overflow-hidden rounded-[14px] bg-[#d8d5c8] text-white focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#3f6b3a]" href="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1466692476868-aef1dfb1e735?auto=format&fit=crop&w=640&h=800&q=70" class="block size-full object-cover transition-[scale,filter] duration-[600ms] ease-[cubic-bezier(.2,.7,.2,1)] motion-reduce:transition-none" width="640" height="800" loading="lazy" alt="Rows of small green seedlings in a black seed tray"><span class="absolute inset-x-0 bottom-0 flex translate-y-[calc(100%-68px)] flex-col gap-0.5 bg-[rgba(24,36,24,.9)] px-[18px] pt-4 pb-[18px] transition-transform duration-400 ease-[cubic-bezier(.2,.7,.2,1)] group-hover:translate-y-0 group-focus-visible:translate-y-0 motion-reduce:transition-none [@media(hover:none)]:translate-y-0"><strong class="text-[1.05rem]">Seed trays</strong><span class="text-[.82rem] text-[#e6e9e1]">Greenhouse, March</span><span class="mt-2.5 text-[.88rem] leading-normal text-[#e6e9e1] opacity-0 transition-opacity duration-300 group-hover:opacity-100 group-focus-visible:opacity-100 motion-reduce:transition-none [@media(hover:none)]:opacity-100">Tomatoes and peppers, sown on the 4th and pricked out three weeks later.</span></span></a><p class="mt-3 block text-[.72rem] tracking-[.12em] text-[#5b6355] uppercase">Slide-up caption</p></li>
    <li><a class="group relative block aspect-[4/5] overflow-hidden rounded-[14px] bg-[#d8d5c8] text-white focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#3f6b3a]" href="https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1465146344425-f00d5f5c8f07?auto=format&fit=crop&w=640&h=800&q=70" class="block size-full object-cover transition-[scale,filter] duration-[600ms] ease-[cubic-bezier(.2,.7,.2,1)] motion-reduce:transition-none grayscale group-hover:grayscale-0 group-focus-visible:grayscale-0" width="640" height="800" loading="lazy" alt="Red poppies growing through a field of pale grass"><span class="absolute inset-x-0 bottom-0 flex flex-col gap-0.5 bg-linear-to-t from-[rgba(16,22,16,.82)] to-[rgba(16,22,16,0)] px-[18px] pt-12 pb-4"><strong class="text-[1.05rem]">Field edge</strong><span class="text-[.82rem] text-[#e6e9e1]">Lower meadow, June</span></span></a><p class="mt-3 block text-[.72rem] tracking-[.12em] text-[#5b6355] uppercase">Greyscale to colour</p></li>
    <li><a class="group relative block aspect-[4/5] overflow-hidden rounded-[14px] bg-[#d8d5c8] text-white focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#3f6b3a] after:absolute after:inset-0 after:bg-[rgba(43,78,40,.82)] after:opacity-0 after:transition-opacity after:duration-[350ms] hover:after:opacity-100 focus-visible:after:opacity-100 motion-reduce:after:transition-none" href="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1565193566173-7a0ee3dbe261?auto=format&fit=crop&w=640&h=800&q=70" class="block size-full object-cover transition-[scale,filter] duration-[600ms] ease-[cubic-bezier(.2,.7,.2,1)] motion-reduce:transition-none" width="640" height="800" loading="lazy" alt="Three white ceramic bottles holding dried poppy seed heads against a dark grey wall"><span class="absolute inset-0 z-[1] flex translate-y-2 items-center justify-center gap-2 font-semibold opacity-0 transition-[opacity,translate] duration-[350ms] group-hover:translate-y-0 group-hover:opacity-100 group-focus-visible:translate-y-0 group-focus-visible:opacity-100 motion-reduce:transition-none [&>svg]:size-[18px]" aria-hidden="true">View series <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></span><span class="absolute inset-x-0 bottom-0 z-[1] flex flex-col gap-0.5 bg-linear-to-t from-[rgba(16,22,16,.82)] to-[rgba(16,22,16,0)] px-[18px] pt-12 pb-4"><strong class="text-[1.05rem]">Bottle vases</strong><span class="text-[.82rem] text-[#e6e9e1]">Studio shelf</span></span></a><p class="mt-3 block text-[.72rem] tracking-[.12em] text-[#5b6355] uppercase">Colour overlay</p></li>
    <li><a class="group relative block aspect-[4/5] overflow-hidden rounded-[14px] bg-[#d8d5c8] text-white focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#3f6b3a] after:absolute after:inset-3.5 after:scale-105 after:rounded-lg after:border-2 after:border-white/92 after:opacity-0 after:transition-[opacity,scale] after:duration-[350ms] hover:after:scale-100 hover:after:opacity-100 focus-visible:after:scale-100 focus-visible:after:opacity-100 motion-reduce:after:transition-none" href="https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1610701596007-11502861dcfa?auto=format&fit=crop&w=640&h=800&q=70" class="block size-full object-cover transition-[scale,filter] duration-[600ms] ease-[cubic-bezier(.2,.7,.2,1)] motion-reduce:transition-none scale-106 group-hover:scale-100 group-focus-visible:scale-100 motion-reduce:scale-100" width="640" height="800" loading="lazy" alt="Speckled stoneware cups in cream and tan glazes on a white shelf"><span class="absolute inset-x-0 bottom-0 flex flex-col gap-0.5 bg-linear-to-t from-[rgba(16,22,16,.82)] to-[rgba(16,22,16,0)] px-[18px] pt-12 pb-4"><strong class="text-[1.05rem]">Stoneware cups</strong><span class="text-[.82rem] text-[#e6e9e1]">Spring firing</span></span></a><p class="mt-3 block text-[.72rem] tracking-[.12em] text-[#5b6355] uppercase">Inset frame</p></li>
    <li><a class="group relative block aspect-[4/5] overflow-hidden rounded-[14px] bg-[#d8d5c8] text-white focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-[#3f6b3a] shadow-[0_2px_6px_rgba(31,42,31,.12)] transition-[translate,box-shadow] duration-300 hover:-translate-y-1.5 hover:shadow-[0_22px_40px_-12px_rgba(31,42,31,.45)] focus-visible:-translate-y-1.5 focus-visible:shadow-[0_22px_40px_-12px_rgba(31,42,31,.45)] motion-reduce:transition-none motion-reduce:hover:translate-y-0 motion-reduce:focus-visible:translate-y-0" href="https://images.unsplash.com/photo-1416879595882-3373a0480b5b?auto=format&fit=crop&w=2000&q=70"><img src="https://images.unsplash.com/photo-1416879595882-3373a0480b5b?auto=format&fit=crop&w=640&h=800&q=70" class="block size-full object-cover transition-[scale,filter] duration-[600ms] ease-[cubic-bezier(.2,.7,.2,1)] motion-reduce:transition-none" width="640" height="800" loading="lazy" alt="A green trowel scooping dark compost beside a small pot"><span class="absolute inset-x-0 bottom-0 flex flex-col gap-0.5 bg-linear-to-t from-[rgba(16,22,16,.82)] to-[rgba(16,22,16,0)] px-[18px] pt-12 pb-4"><strong class="text-[1.05rem]">Potting on</strong><span class="text-[.82rem] text-[#e6e9e1]">Bench work, April</span></span></a><p class="mt-3 block text-[.72rem] tracking-[.12em] text-[#5b6355] uppercase">Lift and shadow</p></li>
  </ul>
</section>

About this set

Six photo tiles from a garden and pottery studio, each showing one hover effect you can lift into any gallery. Zoom scales the photo up gently inside its frame. Slide-up caption shows only the title until the panel slides up to reveal a sentence of detail. Greyscale to colour starts black and white and fills in. Colour overlay washes a green tint over the photo and fades in a View series prompt. Inset frame draws a thin white frame inside the edge while the photo settles back from a slight zoom. Lift and shadow raises the whole tile and deepens its shadow. Every tile is a link, and every effect is triggered by :focus-visible as well as :hover, so keyboard users see exactly what mouse users see; on touch screens, which have no hover, the slide-up details are shown from the start. The effects are built from transform, opacity, filter and box-shadow, so they stay smooth. The Bootstrap version sits on .row-cols-* with a 4:5 .ratio, and the Tailwind version uses group-hover, group-focus-visible and after: utilities.

What’s included

  • Six effects: zoom, slide-up caption, greyscale to colour, colour overlay, inset frame and lift
  • Every effect also runs on keyboard focus
  • Details that hover reveals are shown by default on touch screens
  • Transitions use only transform, opacity, filter and box-shadow
  • No JavaScript

Accessibility

Each tile is a link with descriptive alt text on its photo and a visible title, and shows a 3px outline on keyboard focus. Anything that appears on hover also appears on focus, and on devices without hover the hidden details are shown, so no content depends on a mouse. The View series prompt is decorative and hidden from screen readers. Under prefers-reduced-motion the transitions, zooms and lift are switched off.

Customise it

Set --fx-accent and --fx-radius on .fx, and change the tint colour in .fx-tint::after or the zoom amount in .fx-zoom. In Tailwind edit scale-108, after:bg-[rgba(43,78,40,.82)] and the shadow-[…] values on each tile.