22 / 22
All 22 in 22 Tailwind CSS Image Gallery
- 01Tailwind Hexagon Honeycomb Image Gallery with clip-path
- 02Tailwind Justified Image Gallery with Aspect-Ratio Flex Rows
- 03Tailwind Expanding Panel Image Gallery with Flex-Grow Transitions
- 04Tailwind :has() Hover Spotlight Image Grid
- 05Tailwind Radial Orbit Image Gallery with Counter-Rotating Thumbnails
- 06Tailwind Interactive Pointer Trail Image Gallery
- 07Tailwind Masonry Image Gallery with CSS Columns (No JavaScript)
- 08Tailwind Metro Tile Grid Gallery with Dense Auto-Flow
- 09Tailwind Editorial Magazine Grid Gallery with Blend-Mode Headline
- 10Tailwind Pure CSS Lightbox Gallery with :target (No JavaScript)
- 11Tailwind Filmstrip Carousel Gallery with CSS Scroll-Snap
- 12Tailwind Accordion Image Gallery with Flex-Grow on Hover & Focus
- 13Tailwind Mosaic Grid Gallery with Contained Zoom on Hover
- 14Tailwind Glassmorphism Image Cards with backdrop-blur
- 15Tailwind Diagonal Slice Reveal Gallery with clip-path Halves
- 16Tailwind 3D Tilt Parallax Image Cards with Pointer-Driven Variables
- 17Tailwind 3D Cube Image Viewer with Radio-Driven Rotation
- 18Tailwind 3D Perspective Depth Stack Gallery That Fans on Focus
- 19Tailwind Infinite Scrolling Image Marquee with Seamless Loop
- 20Tailwind Ken Burns Slideshow Gallery with Staggered Cross-Fade
- 21Tailwind Polaroid Photo Stack Gallery with Rotate-on-Hover
- 22Tailwind Scattered Photo Collage with :target Spotlight
Tailwind Scattered Photo Collage with :target Spotlight
A casual collage strewn across a board at random angles; click any photograph and it springs to the centre, straightens and rises above the pile. Deep-linkable, keyboard-operable and script-free — and the port is where Tailwind's ! important modifier earns its place.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tgl-22 relative w-full min-h-svh flex flex-col items-center justify-center gap-4 bg-tgl22-bg font-tgl22-sans px-5 py-10" id="tgl-22" aria-label="Scattered photos collage">
<a href="#tgl-22" aria-label="Reset collage" class="absolute inset-0 z-0"></a>
<div class="relative z-[1] w-[min(820px,100%)] [aspect-ratio:16/10]">
<a id="tgl-22-1" href="#tgl-22-1" style="--rot:-8deg;top:8%;left:10%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1501554728187-ce583db33af7?q=80&w=400&h=300&auto=format&fit=crop" alt="Harbour town from the ferry" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-2" href="#tgl-22-2" style="--rot:6deg;top:14%;left:38%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=300&auto=format&fit=crop" alt="Friends around a table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-3" href="#tgl-22-3" style="--rot:-5deg;top:10%;left:64%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1522312346375-d1a52e2b99b3?q=80&w=400&h=300&auto=format&fit=crop" alt="City street in the evening" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-4" href="#tgl-22-4" style="--rot:9deg;top:46%;left:18%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1490481651871-ab68de25d43d?q=80&w=400&h=300&auto=format&fit=crop" alt="Trail through tall grass" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-5" href="#tgl-22-5" style="--rot:-7deg;top:50%;left:48%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?q=80&w=400&h=300&auto=format&fit=crop" alt="Dinner spread on a long table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-6" href="#tgl-22-6" style="--rot:4deg;top:44%;left:70%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1506126613408-eca07ce68773?q=80&w=400&h=300&auto=format&fit=crop" alt="Beach umbrellas at midday" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
</div>
<p class="relative z-[1] m-0 font-tgl22-mono text-[11px] tracking-[0.14em] uppercase text-tgl22-mut">click a photo to bring it forward · click the background to reset</p>
</section><section class="tgl-22 relative w-full min-h-svh flex flex-col items-center justify-center gap-4 bg-tgl22-bg font-tgl22-sans px-5 py-10" id="tgl-22" aria-label="Scattered photos collage">
<a href="#tgl-22" aria-label="Reset collage" class="absolute inset-0 z-0"></a>
<div class="relative z-[1] w-[min(820px,100%)] [aspect-ratio:16/10]">
<a id="tgl-22-1" href="#tgl-22-1" style="--rot:-8deg;top:8%;left:10%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1501554728187-ce583db33af7?q=80&w=400&h=300&auto=format&fit=crop" alt="Harbour town from the ferry" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-2" href="#tgl-22-2" style="--rot:6deg;top:14%;left:38%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=300&auto=format&fit=crop" alt="Friends around a table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-3" href="#tgl-22-3" style="--rot:-5deg;top:10%;left:64%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1522312346375-d1a52e2b99b3?q=80&w=400&h=300&auto=format&fit=crop" alt="City street in the evening" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-4" href="#tgl-22-4" style="--rot:9deg;top:46%;left:18%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1490481651871-ab68de25d43d?q=80&w=400&h=300&auto=format&fit=crop" alt="Trail through tall grass" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-5" href="#tgl-22-5" style="--rot:-7deg;top:50%;left:48%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?q=80&w=400&h=300&auto=format&fit=crop" alt="Dinner spread on a long table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-6" href="#tgl-22-6" style="--rot:4deg;top:44%;left:70%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1506126613408-eca07ce68773?q=80&w=400&h=300&auto=format&fit=crop" alt="Beach umbrellas at midday" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
</div>
<p class="relative z-[1] m-0 font-tgl22-mono text-[11px] tracking-[0.14em] uppercase text-tgl22-mut">click a photo to bring it forward · click the background to reset</p>
</section>@import "tailwindcss";
@theme {
--color-tgl22-bg: #1c1a17;
--color-tgl22-bg: oklch(0.21 0.008 70);
--color-tgl22-print: #fffdf8;
--color-tgl22-print: oklch(0.99 0.006 90);
--color-tgl22-well: #e0dacd;
--color-tgl22-well: oklch(0.89 0.014 85);
--color-tgl22-mut: #a79c8c;
--color-tgl22-mut: oklch(0.7 0.02 80);
--color-tgl22-acc: #5f8fdc;
--color-tgl22-acc: oklch(0.66 0.14 250);
--font-tgl22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tgl22-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
.tgl-22 {
width: 100%;
min-height: 100svh;
}
.tgl-22 ::selection {
background: var(--color-tgl22-acc);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tgl22-bg: #1c1a17;
--color-tgl22-bg: oklch(0.21 0.008 70);
--color-tgl22-print: #fffdf8;
--color-tgl22-print: oklch(0.99 0.006 90);
--color-tgl22-well: #e0dacd;
--color-tgl22-well: oklch(0.89 0.014 85);
--color-tgl22-mut: #a79c8c;
--color-tgl22-mut: oklch(0.7 0.02 80);
--color-tgl22-acc: #5f8fdc;
--color-tgl22-acc: oklch(0.66 0.14 250);
--font-tgl22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tgl22-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
.tgl-22 {
width: 100%;
min-height: 100svh;
}
.tgl-22 ::selection {
background: var(--color-tgl22-acc);
color: #fff;
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-tgl22-bg: #1c1a17;
--color-tgl22-bg: oklch(0.21 0.008 70);
--color-tgl22-print: #fffdf8;
--color-tgl22-print: oklch(0.99 0.006 90);
--color-tgl22-well: #e0dacd;
--color-tgl22-well: oklch(0.89 0.014 85);
--color-tgl22-mut: #a79c8c;
--color-tgl22-mut: oklch(0.7 0.02 80);
--color-tgl22-acc: #5f8fdc;
--color-tgl22-acc: oklch(0.66 0.14 250);
--font-tgl22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tgl22-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
.tgl-22 {
width: 100%;
min-height: 100svh;
}
.tgl-22 ::selection {
background: var(--color-tgl22-acc);
color: #fff;
}@import "tailwindcss";
@theme {
--color-tgl22-bg: #1c1a17;
--color-tgl22-bg: oklch(0.21 0.008 70);
--color-tgl22-print: #fffdf8;
--color-tgl22-print: oklch(0.99 0.006 90);
--color-tgl22-well: #e0dacd;
--color-tgl22-well: oklch(0.89 0.014 85);
--color-tgl22-mut: #a79c8c;
--color-tgl22-mut: oklch(0.7 0.02 80);
--color-tgl22-acc: #5f8fdc;
--color-tgl22-acc: oklch(0.66 0.14 250);
--font-tgl22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tgl22-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
.tgl-22 {
width: 100%;
min-height: 100svh;
}
.tgl-22 ::selection {
background: var(--color-tgl22-acc);
color: #fff;
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The
!important modifier is used deliberately and only where a class must beat an inline style. Stating it in the class list is better than the CSS version's!importantat the end of a declaration, because the reader sees the override where the override applies. - Scatter coordinates stay inline: they are per-photo data, and every real implementation would render them from a layout table or a random seed.
- UI change from the CSS original: the hint line moved to a lighter token (it sat at 3.2:1 before) and each photograph has descriptive alt text instead of "Collage photo 4".
Here's a working CSS demo 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: Tailwind Scattered Photo Collage with :target Spotlight
Source: https://codefronts.com/snippets/tailwind-css-image-gallery/tailwind-scattered-photo-collage-target-spotlight/
A casual collage strewn across a board at random angles; click any photograph and it springs to the centre, straightens and rises above the pile. Deep-linkable, keyboard-operable and script-free — and the port is where Tailwind's ! important modifier earns its place.
## HTML
```html
<section class="tgl-22 relative w-full min-h-svh flex flex-col items-center justify-center gap-4 bg-tgl22-bg font-tgl22-sans px-5 py-10" id="tgl-22" aria-label="Scattered photos collage">
<a href="#tgl-22" aria-label="Reset collage" class="absolute inset-0 z-0"></a>
<div class="relative z-[1] w-[min(820px,100%)] [aspect-ratio:16/10]">
<a id="tgl-22-1" href="#tgl-22-1" style="--rot:-8deg;top:8%;left:10%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1501554728187-ce583db33af7?q=80&w=400&h=300&auto=format&fit=crop" alt="Harbour town from the ferry" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-2" href="#tgl-22-2" style="--rot:6deg;top:14%;left:38%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=300&auto=format&fit=crop" alt="Friends around a table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-3" href="#tgl-22-3" style="--rot:-5deg;top:10%;left:64%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1522312346375-d1a52e2b99b3?q=80&w=400&h=300&auto=format&fit=crop" alt="City street in the evening" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-4" href="#tgl-22-4" style="--rot:9deg;top:46%;left:18%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1490481651871-ab68de25d43d?q=80&w=400&h=300&auto=format&fit=crop" alt="Trail through tall grass" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-5" href="#tgl-22-5" style="--rot:-7deg;top:50%;left:48%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?q=80&w=400&h=300&auto=format&fit=crop" alt="Dinner spread on a long table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-6" href="#tgl-22-6" style="--rot:4deg;top:44%;left:70%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1506126613408-eca07ce68773?q=80&w=400&h=300&auto=format&fit=crop" alt="Beach umbrellas at midday" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
</div>
<p class="relative z-[1] m-0 font-tgl22-mono text-[11px] tracking-[0.14em] uppercase text-tgl22-mut">click a photo to bring it forward · click the background to reset</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgl22-bg: #1c1a17;
--color-tgl22-bg: oklch(0.21 0.008 70);
--color-tgl22-print: #fffdf8;
--color-tgl22-print: oklch(0.99 0.006 90);
--color-tgl22-well: #e0dacd;
--color-tgl22-well: oklch(0.89 0.014 85);
--color-tgl22-mut: #a79c8c;
--color-tgl22-mut: oklch(0.7 0.02 80);
--color-tgl22-acc: #5f8fdc;
--color-tgl22-acc: oklch(0.66 0.14 250);
--font-tgl22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tgl22-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
.tgl-22 {
width: 100%;
min-height: 100svh;
}
.tgl-22 ::selection {
background: var(--color-tgl22-acc);
color: #fff;
}
```Here's a working CSS demo 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: Tailwind Scattered Photo Collage with :target Spotlight
Source: https://codefronts.com/snippets/tailwind-css-image-gallery/tailwind-scattered-photo-collage-target-spotlight/
A casual collage strewn across a board at random angles; click any photograph and it springs to the centre, straightens and rises above the pile. Deep-linkable, keyboard-operable and script-free — and the port is where Tailwind's ! important modifier earns its place.
## HTML
```html
<section class="tgl-22 relative w-full min-h-svh flex flex-col items-center justify-center gap-4 bg-tgl22-bg font-tgl22-sans px-5 py-10" id="tgl-22" aria-label="Scattered photos collage">
<a href="#tgl-22" aria-label="Reset collage" class="absolute inset-0 z-0"></a>
<div class="relative z-[1] w-[min(820px,100%)] [aspect-ratio:16/10]">
<a id="tgl-22-1" href="#tgl-22-1" style="--rot:-8deg;top:8%;left:10%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1501554728187-ce583db33af7?q=80&w=400&h=300&auto=format&fit=crop" alt="Harbour town from the ferry" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-2" href="#tgl-22-2" style="--rot:6deg;top:14%;left:38%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1589003077984-894e133dabab?q=80&w=400&h=300&auto=format&fit=crop" alt="Friends around a table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-3" href="#tgl-22-3" style="--rot:-5deg;top:10%;left:64%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1522312346375-d1a52e2b99b3?q=80&w=400&h=300&auto=format&fit=crop" alt="City street in the evening" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-4" href="#tgl-22-4" style="--rot:9deg;top:46%;left:18%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1490481651871-ab68de25d43d?q=80&w=400&h=300&auto=format&fit=crop" alt="Trail through tall grass" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-5" href="#tgl-22-5" style="--rot:-7deg;top:50%;left:48%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?q=80&w=400&h=300&auto=format&fit=crop" alt="Dinner spread on a long table" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
<a id="tgl-22-6" href="#tgl-22-6" style="--rot:4deg;top:44%;left:70%" class="absolute w-[26%] p-2 rounded-sm overflow-hidden bg-tgl22-print no-underline origin-center [transform:rotate(var(--rot))] shadow-[0_12px_28px_-12px_rgba(0,0,0,0.7)] transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)] hover:z-[6] hover:[transform:rotate(var(--rot))_scale(1.04)] target:top-1/2! target:left-1/2! target:z-[10] target:[transform:translate(-50%,-50%)_rotate(0deg)_scale(1.5)] focus-visible:outline-3 focus-visible:outline-tgl22-acc focus-visible:outline-offset-[3px] motion-reduce:transition-none max-[560px]:w-[38%]"><img src="https://images.unsplash.com/photo-1506126613408-eca07ce68773?q=80&w=400&h=300&auto=format&fit=crop" alt="Beach umbrellas at midday" loading="lazy" decoding="async" class="block w-full [aspect-ratio:4/3] object-cover bg-tgl22-well"></a>
</div>
<p class="relative z-[1] m-0 font-tgl22-mono text-[11px] tracking-[0.14em] uppercase text-tgl22-mut">click a photo to bring it forward · click the background to reset</p>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tgl22-bg: #1c1a17;
--color-tgl22-bg: oklch(0.21 0.008 70);
--color-tgl22-print: #fffdf8;
--color-tgl22-print: oklch(0.99 0.006 90);
--color-tgl22-well: #e0dacd;
--color-tgl22-well: oklch(0.89 0.014 85);
--color-tgl22-mut: #a79c8c;
--color-tgl22-mut: oklch(0.7 0.02 80);
--color-tgl22-acc: #5f8fdc;
--color-tgl22-acc: oklch(0.66 0.14 250);
--font-tgl22-sans: 'Space Grotesk', system-ui, sans-serif;
--font-tgl22-mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
.tgl-22 {
width: 100%;
min-height: 100svh;
}
.tgl-22 ::selection {
background: var(--color-tgl22-acc);
color: #fff;
}
```How this works
The fragment picks the photograph. Each print is an anchor pointing at its own id; becoming :target switches it to the centred pose. The URL holds the state, so a spotlighted photo can be linked, bookmarked and reloaded.
! is the honest answer here. The resting position lives in an inline style attribute — it is per-photo data — and inline styles beat any class. Tailwind's important modifier states the override explicitly rather than hiding it behind specificity arithmetic:
class="target:top-1/2! target:left-1/2!"Everything is focusable. Real anchors throughout, so the board can be tabbed and Enter spotlights a photo exactly as a click does.
Make it yours
- Reposition prints by editing each one's inline
top/left/--rot. - Change the spotlight pose — scale, angle, position — in the shared
target:transform. - Fan the pile into an arc by patterning the coordinates rather than scattering them.
Gotchas — read before shipping
- The spotlit photo needs the highest
z-index, or it centres itself underneath the pile. - Always provide the background reset anchor; without a way out, the board is a one-way trip.
- Position overrides need
!because the resting coordinates are inline styles. This is the rare correct use of the important modifier — a class cannot outrank an inline style otherwise.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
:target, absolute positioning and transforms are universal; the floor is Tailwind v4's generated sheet.