17 / 20
All 20 in 20 Tailwind CSS Image Hover Effects
- 01Tailwind Image Hover Zoom In Card
- 02Tailwind Hover Reveal Text Over Image
- 03Tailwind E-Commerce Product Image Swap on Hover
- 04Tailwind Grid Image Blur Overlay Text Hover
- 05Tailwind Card Slide Up Caption on Hover
- 06Tailwind Grayscale to Color Image Hover
- 07Tailwind Image Color Overlay Tint on Hover
- 08Tailwind Neumorphic Image Card Hover Effect
- 09Tailwind Glassmorphism Overlay on Image Hover
- 10Tailwind Glowing Neon Border Image Hover
- 11Tailwind Image Clip-Path Transition Hover
- 12Tailwind Image Tilt 3D Perspective Hover
- 13Tailwind Shining Light Glare Image Hover
- 14Tailwind Image Split Transition Hover
- 15Tailwind Image Ripple Animation Hover
- 16Tailwind Circular Team Profile Avatar Hover
- 17Tailwind Fullscreen Background Image Hover
- 18Tailwind Masonry Gallery Zoom Hover
- 19Tailwind Image Icon Reveal Center Hover
- 20Tailwind Image Card Flip 3D Animation Hover
Tailwind Fullscreen Background Image Hover
A nav where hovering an item swaps the whole viewport background — and the port replaces six class toggles with one attribute. The stage carries data-active="3"; each panel reads it through group-data-[active=3]:opacity-100. The script sets one value and never touches a class list.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tih-17 group w-full min-h-svh relative overflow-hidden bg-tih17-bg font-tih17-sans" data-active="0" aria-label="Fullscreen background swap on hover demo">
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
<div class="absolute inset-0 opacity-0 scale-104 bg-linear-[135deg,oklch(0.1_0_0),oklch(0.17_0_0)] transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=0]:opacity-100 group-data-[active=0]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-universe/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.34_0.12_285),oklch(0.28_0.06_290))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=1]:opacity-100 group-data-[active=1]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-canopy/1600/900'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=2]:opacity-100 group-data-[active=2]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-dunes/1600/900'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.32_0.08_55),oklch(0.48_0.11_60))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=3]:opacity-100 group-data-[active=3]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-violet/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_310),oklch(0.35_0.18_298),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=4]:opacity-100 group-data-[active=4]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-ocean/1600/900'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.5_0.2_260))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=5]:opacity-100 group-data-[active=5]:scale-100 motion-reduce:duration-0"></div>
</div>
<nav class="relative z-2 flex flex-col justify-center min-h-svh p-10" aria-label="Background preview">
<p class="mb-5 text-[10px] font-bold tracking-[0.14em] uppercase text-tih17-muted">Navigate · hover or focus to preview</p>
<ul class="list-none flex flex-col gap-1">
<li><a href="#deep-universe" data-target="1" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">01</span>
<span class="text-sm" aria-hidden="true">🌌</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Deep Universe</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#wild-canopy" data-target="2" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">02</span>
<span class="text-sm" aria-hidden="true">🌿</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Wild Canopy</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#desert-dunes" data-target="3" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">03</span>
<span class="text-sm" aria-hidden="true">🏜</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Desert Dunes</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#violet-dreams" data-target="4" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">04</span>
<span class="text-sm" aria-hidden="true">🔮</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Violet Dreams</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#ocean-horizon" data-target="5" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">05</span>
<span class="text-sm" aria-hidden="true">🌊</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Ocean Horizon</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
</ul>
</nav>
</section><section class="tih-17 group w-full min-h-svh relative overflow-hidden bg-tih17-bg font-tih17-sans" data-active="0" aria-label="Fullscreen background swap on hover demo">
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
<div class="absolute inset-0 opacity-0 scale-104 bg-linear-[135deg,oklch(0.1_0_0),oklch(0.17_0_0)] transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=0]:opacity-100 group-data-[active=0]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-universe/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.34_0.12_285),oklch(0.28_0.06_290))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=1]:opacity-100 group-data-[active=1]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-canopy/1600/900'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=2]:opacity-100 group-data-[active=2]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-dunes/1600/900'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.32_0.08_55),oklch(0.48_0.11_60))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=3]:opacity-100 group-data-[active=3]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-violet/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_310),oklch(0.35_0.18_298),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=4]:opacity-100 group-data-[active=4]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-ocean/1600/900'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.5_0.2_260))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=5]:opacity-100 group-data-[active=5]:scale-100 motion-reduce:duration-0"></div>
</div>
<nav class="relative z-2 flex flex-col justify-center min-h-svh p-10" aria-label="Background preview">
<p class="mb-5 text-[10px] font-bold tracking-[0.14em] uppercase text-tih17-muted">Navigate · hover or focus to preview</p>
<ul class="list-none flex flex-col gap-1">
<li><a href="#deep-universe" data-target="1" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">01</span>
<span class="text-sm" aria-hidden="true">🌌</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Deep Universe</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#wild-canopy" data-target="2" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">02</span>
<span class="text-sm" aria-hidden="true">🌿</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Wild Canopy</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#desert-dunes" data-target="3" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">03</span>
<span class="text-sm" aria-hidden="true">🏜</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Desert Dunes</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#violet-dreams" data-target="4" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">04</span>
<span class="text-sm" aria-hidden="true">🔮</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Violet Dreams</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#ocean-horizon" data-target="5" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">05</span>
<span class="text-sm" aria-hidden="true">🌊</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Ocean Horizon</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
</ul>
</nav>
</section>@import "tailwindcss";
@theme {
--color-tih17-bg: #06060a;
--color-tih17-bg: oklch(0.1 0.008 285);
--color-tih17-text: #f1f5f9;
--color-tih17-text: oklch(0.96 0.005 250);
--color-tih17-muted: #64748b;
--color-tih17-muted: oklch(0.58 0.035 255);
--color-tih17-acc: #f472b6;
--color-tih17-acc: oklch(0.72 0.16 350);
--font-tih17-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih17: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-17 {
width: 100%;
min-height: 100svh;
}
.tih-17 ::selection {
background: oklch(0.72 0.16 350);
color: #000;
}@import "tailwindcss";
@theme {
--color-tih17-bg: #06060a;
--color-tih17-bg: oklch(0.1 0.008 285);
--color-tih17-text: #f1f5f9;
--color-tih17-text: oklch(0.96 0.005 250);
--color-tih17-muted: #64748b;
--color-tih17-muted: oklch(0.58 0.035 255);
--color-tih17-acc: #f472b6;
--color-tih17-acc: oklch(0.72 0.16 350);
--font-tih17-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih17: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-17 {
width: 100%;
min-height: 100svh;
}
.tih-17 ::selection {
background: oklch(0.72 0.16 350);
color: #000;
}(function () {
document.querySelectorAll('.tih-17').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
function set(v) { stage.setAttribute('data-active', String(v)); }
stage.querySelectorAll('a[data-target]').forEach(function (link) {
link.addEventListener('pointerenter', function () { set(link.dataset.target); });
link.addEventListener('pointerleave', function () { set(0); });
link.addEventListener('focus', function () { set(link.dataset.target); });
link.addEventListener('blur', function () { set(0); });
link.addEventListener('click', function (e) { e.preventDefault(); });
});
document.addEventListener('touchstart', function (e) {
if (!stage.contains(e.target)) set(0);
}, { passive: true });
});
})();(function () {
document.querySelectorAll('.tih-17').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
function set(v) { stage.setAttribute('data-active', String(v)); }
stage.querySelectorAll('a[data-target]').forEach(function (link) {
link.addEventListener('pointerenter', function () { set(link.dataset.target); });
link.addEventListener('pointerleave', function () { set(0); });
link.addEventListener('focus', function () { set(link.dataset.target); });
link.addEventListener('blur', function () { set(0); });
link.addEventListener('click', function (e) { e.preventDefault(); });
});
document.addEventListener('touchstart', function (e) {
if (!stage.contains(e.target)) set(0);
}, { passive: true });
});
})();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-tih17-bg: #06060a;
--color-tih17-bg: oklch(0.1 0.008 285);
--color-tih17-text: #f1f5f9;
--color-tih17-text: oklch(0.96 0.005 250);
--color-tih17-muted: #64748b;
--color-tih17-muted: oklch(0.58 0.035 255);
--color-tih17-acc: #f472b6;
--color-tih17-acc: oklch(0.72 0.16 350);
--font-tih17-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih17: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-17 {
width: 100%;
min-height: 100svh;
}
.tih-17 ::selection {
background: oklch(0.72 0.16 350);
color: #000;
}@import "tailwindcss";
@theme {
--color-tih17-bg: #06060a;
--color-tih17-bg: oklch(0.1 0.008 285);
--color-tih17-text: #f1f5f9;
--color-tih17-text: oklch(0.96 0.005 250);
--color-tih17-muted: #64748b;
--color-tih17-muted: oklch(0.58 0.035 255);
--color-tih17-acc: #f472b6;
--color-tih17-acc: oklch(0.72 0.16 350);
--font-tih17-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih17: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-17 {
width: 100%;
min-height: 100svh;
}
.tih-17 ::selection {
background: oklch(0.72 0.16 350);
color: #000;
}<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;600&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;600&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- Six
classList.togglecalls per pointer move become onesetAttribute, and the visibility rule moves onto each panel asgroup-data-[active=N]:. This is the port's cleanest state-machine win. - The bracket form is mandatory here:
data-activecarries a value, so the booleangroup-data-active:shorthand would match always and show all six panels. focus/blurhandlers andgroup-focus-visible/link:variants are added by the port — the CSS version lists keyboard support as a customization, which means shipping it broken.- Named groups (
group/link) keep the per-link label and arrow states from colliding with the stage's owngroup. Without the name,group-hover:on a label would fire whenever the section is hovered. - The iOS
touchstartreset is implemented rather than suggested. It is four lines and it is the difference between the pattern working on a phone and not. motion-reduce:duration-0keeps the swap instant; the panels still need to change value, sotransition-nonewould be the wrong tool.
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 Fullscreen Background Image Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-fullscreen-background-image-hover/
A nav where hovering an item swaps the whole viewport background — and the port replaces six class toggles with one attribute. The stage carries data-active="3"; each panel reads it through group-data-[active=3]:opacity-100. The script sets one value and never touches a class list.
## HTML
```html
<section class="tih-17 group w-full min-h-svh relative overflow-hidden bg-tih17-bg font-tih17-sans" data-active="0" aria-label="Fullscreen background swap on hover demo">
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
<div class="absolute inset-0 opacity-0 scale-104 bg-linear-[135deg,oklch(0.1_0_0),oklch(0.17_0_0)] transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=0]:opacity-100 group-data-[active=0]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-universe/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.34_0.12_285),oklch(0.28_0.06_290))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=1]:opacity-100 group-data-[active=1]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-canopy/1600/900'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=2]:opacity-100 group-data-[active=2]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-dunes/1600/900'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.32_0.08_55),oklch(0.48_0.11_60))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=3]:opacity-100 group-data-[active=3]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-violet/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_310),oklch(0.35_0.18_298),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=4]:opacity-100 group-data-[active=4]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-ocean/1600/900'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.5_0.2_260))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=5]:opacity-100 group-data-[active=5]:scale-100 motion-reduce:duration-0"></div>
</div>
<nav class="relative z-2 flex flex-col justify-center min-h-svh p-10" aria-label="Background preview">
<p class="mb-5 text-[10px] font-bold tracking-[0.14em] uppercase text-tih17-muted">Navigate · hover or focus to preview</p>
<ul class="list-none flex flex-col gap-1">
<li><a href="#deep-universe" data-target="1" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">01</span>
<span class="text-sm" aria-hidden="true">🌌</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Deep Universe</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#wild-canopy" data-target="2" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">02</span>
<span class="text-sm" aria-hidden="true">🌿</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Wild Canopy</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#desert-dunes" data-target="3" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">03</span>
<span class="text-sm" aria-hidden="true">🏜</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Desert Dunes</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#violet-dreams" data-target="4" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">04</span>
<span class="text-sm" aria-hidden="true">🔮</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Violet Dreams</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#ocean-horizon" data-target="5" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">05</span>
<span class="text-sm" aria-hidden="true">🌊</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Ocean Horizon</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
</ul>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih17-bg: #06060a;
--color-tih17-bg: oklch(0.1 0.008 285);
--color-tih17-text: #f1f5f9;
--color-tih17-text: oklch(0.96 0.005 250);
--color-tih17-muted: #64748b;
--color-tih17-muted: oklch(0.58 0.035 255);
--color-tih17-acc: #f472b6;
--color-tih17-acc: oklch(0.72 0.16 350);
--font-tih17-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih17: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-17 {
width: 100%;
min-height: 100svh;
}
.tih-17 ::selection {
background: oklch(0.72 0.16 350);
color: #000;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tih-17').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
function set(v) { stage.setAttribute('data-active', String(v)); }
stage.querySelectorAll('a[data-target]').forEach(function (link) {
link.addEventListener('pointerenter', function () { set(link.dataset.target); });
link.addEventListener('pointerleave', function () { set(0); });
link.addEventListener('focus', function () { set(link.dataset.target); });
link.addEventListener('blur', function () { set(0); });
link.addEventListener('click', function (e) { e.preventDefault(); });
});
document.addEventListener('touchstart', function (e) {
if (!stage.contains(e.target)) set(0);
}, { passive: true });
});
})();
```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 Fullscreen Background Image Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-fullscreen-background-image-hover/
A nav where hovering an item swaps the whole viewport background — and the port replaces six class toggles with one attribute. The stage carries data-active="3"; each panel reads it through group-data-[active=3]:opacity-100. The script sets one value and never touches a class list.
## HTML
```html
<section class="tih-17 group w-full min-h-svh relative overflow-hidden bg-tih17-bg font-tih17-sans" data-active="0" aria-label="Fullscreen background swap on hover demo">
<div class="absolute inset-0 pointer-events-none" aria-hidden="true">
<div class="absolute inset-0 opacity-0 scale-104 bg-linear-[135deg,oklch(0.1_0_0),oklch(0.17_0_0)] transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=0]:opacity-100 group-data-[active=0]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-universe/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_285),oklch(0.34_0.12_285),oklch(0.28_0.06_290))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=1]:opacity-100 group-data-[active=1]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-canopy/1600/900'),linear-gradient(135deg,oklch(0.2_0.04_190),oklch(0.42_0.09_165),oklch(0.6_0.13_163))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=2]:opacity-100 group-data-[active=2]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-dunes/1600/900'),linear-gradient(135deg,oklch(0.18_0.03_60),oklch(0.32_0.08_55),oklch(0.48_0.11_60))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=3]:opacity-100 group-data-[active=3]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-violet/1600/900'),linear-gradient(135deg,oklch(0.17_0.07_310),oklch(0.35_0.18_298),oklch(0.55_0.24_295))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=4]:opacity-100 group-data-[active=4]:scale-100 motion-reduce:duration-0"></div>
<div class="absolute inset-0 opacity-0 scale-104 bg-[image:url('https://picsum.photos/seed/tih17-ocean/1600/900'),linear-gradient(135deg,oklch(0.17_0.08_265),oklch(0.33_0.14_262),oklch(0.5_0.2_260))] bg-cover bg-center bg-no-repeat transition-[opacity,scale] duration-600 ease-tih17 group-data-[active=5]:opacity-100 group-data-[active=5]:scale-100 motion-reduce:duration-0"></div>
</div>
<nav class="relative z-2 flex flex-col justify-center min-h-svh p-10" aria-label="Background preview">
<p class="mb-5 text-[10px] font-bold tracking-[0.14em] uppercase text-tih17-muted">Navigate · hover or focus to preview</p>
<ul class="list-none flex flex-col gap-1">
<li><a href="#deep-universe" data-target="1" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">01</span>
<span class="text-sm" aria-hidden="true">🌌</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Deep Universe</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#wild-canopy" data-target="2" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">02</span>
<span class="text-sm" aria-hidden="true">🌿</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Wild Canopy</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#desert-dunes" data-target="3" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">03</span>
<span class="text-sm" aria-hidden="true">🏜</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Desert Dunes</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#violet-dreams" data-target="4" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">04</span>
<span class="text-sm" aria-hidden="true">🔮</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Violet Dreams</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
<li><a href="#ocean-horizon" data-target="5" class="group/link flex items-center gap-3 min-h-11 px-3 py-2.5 rounded-lg no-underline transition-colors duration-200 hover:bg-[oklch(1_0_0/0.06)] focus-visible:bg-[oklch(1_0_0/0.06)] focus-visible:outline-2 focus-visible:outline-tih17-acc focus-visible:outline-offset-2">
<span class="w-5.5 shrink-0 text-[11px] font-semibold text-tih17-muted tabular-nums">05</span>
<span class="text-sm" aria-hidden="true">🌊</span>
<span class="text-xl font-extrabold tracking-[-0.02em] text-[oklch(1_0_0/0.25)] transition-[color,translate] duration-600 ease-tih17 group-hover/link:text-tih17-text group-hover/link:translate-x-1.5 group-focus-visible/link:text-tih17-text motion-reduce:transition-none">Ocean Horizon</span>
<span class="ml-auto text-base text-tih17-acc opacity-0 -translate-x-2 transition-[opacity,translate] duration-200 group-hover/link:opacity-100 group-hover/link:translate-x-0 group-focus-visible/link:opacity-100 group-focus-visible/link:translate-x-0" aria-hidden="true">→</span>
</a></li>
</ul>
</nav>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih17-bg: #06060a;
--color-tih17-bg: oklch(0.1 0.008 285);
--color-tih17-text: #f1f5f9;
--color-tih17-text: oklch(0.96 0.005 250);
--color-tih17-muted: #64748b;
--color-tih17-muted: oklch(0.58 0.035 255);
--color-tih17-acc: #f472b6;
--color-tih17-acc: oklch(0.72 0.16 350);
--font-tih17-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih17: cubic-bezier(0.16, 1, 0.3, 1);
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's
w-full min-h-svh, so the stage is correctly sized before the browser build compiles. */
.tih-17 {
width: 100%;
min-height: 100svh;
}
.tih-17 ::selection {
background: oklch(0.72 0.16 350);
color: #000;
}
```
## JavaScript
```js
(function () {
document.querySelectorAll('.tih-17').forEach(function (stage) {
if (stage.dataset.bound) return; stage.dataset.bound = '1';
function set(v) { stage.setAttribute('data-active', String(v)); }
stage.querySelectorAll('a[data-target]').forEach(function (link) {
link.addEventListener('pointerenter', function () { set(link.dataset.target); });
link.addEventListener('pointerleave', function () { set(0); });
link.addEventListener('focus', function () { set(link.dataset.target); });
link.addEventListener('blur', function () { set(0); });
link.addEventListener('click', function (e) { e.preventDefault(); });
});
document.addEventListener('touchstart', function (e) {
if (!stage.contains(e.target)) set(0);
}, { passive: true });
});
})();
```How this works
One attribute, six readers.
<section class="group" data-active="0">
<div class="absolute inset-0 opacity-0 scale-104
group-data-[active=1]:opacity-100
group-data-[active=1]:scale-100">…The CSS version toggles an is-active class on six elements every time the pointer moves between links. Here the script writes one attribute value and the cascade resolves which panel is visible — fewer DOM writes, and the styling rule lives on the panel it applies to.
The value form is required. group-data-open: is the boolean shorthand for a bare attribute; an attribute that carries a value needs the bracket form group-data-[active=3]:. Mixing them up is the most common mistake with this variant.
Focus is not optional. Hover-only preview means a keyboard user navigates a list with no feedback at all. Adding focus/blur to the same handler is four lines and makes the pattern usable.
Make it yours
- Add a panel: one more
<div>with the nextgroup-data-[active=N]:pair, one more link with a matchingdata-target. - Depth-of-field exit: add
blur-smto the resting state andgroup-data-[active=N]:blur-none. - Deliberate entrance:
delay-50on the scale half only. - Auto-cycle when idle: a timer that increments
data-active; the CSS needs no changes at all. - Retheme through
--color-tih17-acc, which paints the arrow and every focus ring.
Gotchas — read before shipping
- Use the bracket form for valued attributes.
group-data-active:matches the attribute's mere presence, which here is always true — every panel would show at once. - The default panel must be the initial
data-activevalue in the markup, or the stage is blank until the first hover. - The panel stack needs
pointer-events-none; it covers the nav. - iOS does not fire
pointerleavereliably after a tap. The script adds a document-level reset, which the CSS version only mentions as advice. - Six large stacked images all decode at once. Real photography here wants lazy loading and preload hints.
- The browser CDN build compiles in the page and is for prototyping only. Ship the CLI or a plugin build.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Attribute selectors and opacity transitions are universal; with JS disabled the default panel shows and the nav still works as links.