10 / 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 Glowing Neon Border Image Hover
Three stacked shadows in one property — hairline, 20px bloom, 60px ambient — driven by a per-card --glow custom property, so one class list glows in three colours. The corner brackets, which the CSS version builds from two pseudo-elements, become before: and after: utilities on the frame.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="tih-10 w-full min-h-svh grid place-items-center bg-tih10-bg font-tih10-sans px-6 py-10" aria-label="Neon glow border image hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article style="--glow:oklch(0.82 0.15 320); --glow-dim:oklch(0.82 0.15 320/0.25); --glow2:oklch(0.79 0.13 205)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-gpu/600/600'),linear-gradient(135deg,oklch(0.16_0.06_305),oklch(0.28_0.14_305),oklch(0.42_0.2_302))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Cipher X9 GPU</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">24GB GDDR7 · Ray Tracing</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 98 / 100 Performance</p>
</div>
</article>
<article style="--glow:oklch(0.79 0.13 205); --glow-dim:oklch(0.79 0.13 205/0.25); --glow2:oklch(0.88 0.13 150)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-oled/600/600'),linear-gradient(135deg,oklch(0.17_0.04_230),oklch(0.3_0.07_230),oklch(0.42_0.1_232))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Horizon 4K OLED</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">240Hz · 1ms GTG · HDR</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 96 / 100 Visuals</p>
</div>
</article>
<article style="--glow:oklch(0.88 0.13 150); --glow-dim:oklch(0.88 0.13 150/0.25); --glow2:oklch(0.82 0.15 320)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-keyboard/600/600'),linear-gradient(135deg,oklch(0.16_0.04_160),oklch(0.3_0.08_162),oklch(0.38_0.09_163))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Spectra 75% MK</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">Optical · Per-key RGB</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 94 / 100 Feel</p>
</div>
</article>
</div>
</section><section class="tih-10 w-full min-h-svh grid place-items-center bg-tih10-bg font-tih10-sans px-6 py-10" aria-label="Neon glow border image hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article style="--glow:oklch(0.82 0.15 320); --glow-dim:oklch(0.82 0.15 320/0.25); --glow2:oklch(0.79 0.13 205)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-gpu/600/600'),linear-gradient(135deg,oklch(0.16_0.06_305),oklch(0.28_0.14_305),oklch(0.42_0.2_302))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Cipher X9 GPU</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">24GB GDDR7 · Ray Tracing</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 98 / 100 Performance</p>
</div>
</article>
<article style="--glow:oklch(0.79 0.13 205); --glow-dim:oklch(0.79 0.13 205/0.25); --glow2:oklch(0.88 0.13 150)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-oled/600/600'),linear-gradient(135deg,oklch(0.17_0.04_230),oklch(0.3_0.07_230),oklch(0.42_0.1_232))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Horizon 4K OLED</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">240Hz · 1ms GTG · HDR</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 96 / 100 Visuals</p>
</div>
</article>
<article style="--glow:oklch(0.88 0.13 150); --glow-dim:oklch(0.88 0.13 150/0.25); --glow2:oklch(0.82 0.15 320)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-keyboard/600/600'),linear-gradient(135deg,oklch(0.16_0.04_160),oklch(0.3_0.08_162),oklch(0.38_0.09_163))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Spectra 75% MK</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">Optical · Per-key RGB</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 94 / 100 Feel</p>
</div>
</article>
</div>
</section>@import "tailwindcss";
@theme {
--color-tih10-bg: #030308;
--color-tih10-bg: oklch(0.08 0.008 285);
--color-tih10-text: #f1f5f9;
--color-tih10-text: oklch(0.96 0.005 250);
--color-tih10-muted: #64748b;
--color-tih10-muted: oklch(0.58 0.035 255);
--font-tih10-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih10: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 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-10 {
width: 100%;
min-height: 100svh;
}
.tih-10 ::selection {
background: oklch(0.82 0.15 320);
color: #000;
}@import "tailwindcss";
@theme {
--color-tih10-bg: #030308;
--color-tih10-bg: oklch(0.08 0.008 285);
--color-tih10-text: #f1f5f9;
--color-tih10-text: oklch(0.96 0.005 250);
--color-tih10-muted: #64748b;
--color-tih10-muted: oklch(0.58 0.035 255);
--font-tih10-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih10: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 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-10 {
width: 100%;
min-height: 100svh;
}
.tih-10 ::selection {
background: oklch(0.82 0.15 320);
color: #000;
}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-tih10-bg: #030308;
--color-tih10-bg: oklch(0.08 0.008 285);
--color-tih10-text: #f1f5f9;
--color-tih10-text: oklch(0.96 0.005 250);
--color-tih10-muted: #64748b;
--color-tih10-muted: oklch(0.58 0.035 255);
--font-tih10-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih10: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 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-10 {
width: 100%;
min-height: 100svh;
}
.tih-10 ::selection {
background: oklch(0.82 0.15 320);
color: #000;
}@import "tailwindcss";
@theme {
--color-tih10-bg: #030308;
--color-tih10-bg: oklch(0.08 0.008 285);
--color-tih10-text: #f1f5f9;
--color-tih10-text: oklch(0.96 0.005 250);
--color-tih10-muted: #64748b;
--color-tih10-muted: oklch(0.58 0.035 255);
--font-tih10-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih10: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 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-10 {
width: 100%;
min-height: 100svh;
}
.tih-10 ::selection {
background: oklch(0.82 0.15 320);
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.
- Three per-colour
:hoverrules become one arbitrary shadow utility reading an inline--glow. Adding a fourth colour is a new card, not new CSS. - Both corner brackets move into
before:/after:variant chains, selective borders included. This is the demo where pseudo-element variants pay off most clearly. group-hover:before:opacity-100is a stacked variant — group state plus pseudo-element, which is exactly the.card:hover .img::beforeselector expressed on the element itself.text-[var(--glow)]makesborder-currentwork on the brackets, so the bracket colour follows the glow with no second property.- The gradient score line becomes
bg-clip-text text-transparentplus a gradient utility — three utilities replacing four declarations and two per-card overrides. - The glow and the clip live on different elements: the card glows, the inner frame clips. That separation has to be deliberate, and utilities make it visible at a glance.
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 Glowing Neon Border Image Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-glowing-neon-border-image-hover/
Three stacked shadows in one property — hairline, 20px bloom, 60px ambient — driven by a per-card --glow custom property, so one class list glows in three colours. The corner brackets, which the CSS version builds from two pseudo-elements, become before: and after: utilities on the frame.
## HTML
```html
<section class="tih-10 w-full min-h-svh grid place-items-center bg-tih10-bg font-tih10-sans px-6 py-10" aria-label="Neon glow border image hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article style="--glow:oklch(0.82 0.15 320); --glow-dim:oklch(0.82 0.15 320/0.25); --glow2:oklch(0.79 0.13 205)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-gpu/600/600'),linear-gradient(135deg,oklch(0.16_0.06_305),oklch(0.28_0.14_305),oklch(0.42_0.2_302))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Cipher X9 GPU</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">24GB GDDR7 · Ray Tracing</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 98 / 100 Performance</p>
</div>
</article>
<article style="--glow:oklch(0.79 0.13 205); --glow-dim:oklch(0.79 0.13 205/0.25); --glow2:oklch(0.88 0.13 150)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-oled/600/600'),linear-gradient(135deg,oklch(0.17_0.04_230),oklch(0.3_0.07_230),oklch(0.42_0.1_232))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Horizon 4K OLED</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">240Hz · 1ms GTG · HDR</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 96 / 100 Visuals</p>
</div>
</article>
<article style="--glow:oklch(0.88 0.13 150); --glow-dim:oklch(0.88 0.13 150/0.25); --glow2:oklch(0.82 0.15 320)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-keyboard/600/600'),linear-gradient(135deg,oklch(0.16_0.04_160),oklch(0.3_0.08_162),oklch(0.38_0.09_163))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Spectra 75% MK</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">Optical · Per-key RGB</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 94 / 100 Feel</p>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih10-bg: #030308;
--color-tih10-bg: oklch(0.08 0.008 285);
--color-tih10-text: #f1f5f9;
--color-tih10-text: oklch(0.96 0.005 250);
--color-tih10-muted: #64748b;
--color-tih10-muted: oklch(0.58 0.035 255);
--font-tih10-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih10: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 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-10 {
width: 100%;
min-height: 100svh;
}
.tih-10 ::selection {
background: oklch(0.82 0.15 320);
color: #000;
}
```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 Glowing Neon Border Image Hover
Source: https://codefronts.com/motion/tailwind-css-image-hover-effects/tailwind-glowing-neon-border-image-hover/
Three stacked shadows in one property — hairline, 20px bloom, 60px ambient — driven by a per-card --glow custom property, so one class list glows in three colours. The corner brackets, which the CSS version builds from two pseudo-elements, become before: and after: utilities on the frame.
## HTML
```html
<section class="tih-10 w-full min-h-svh grid place-items-center bg-tih10-bg font-tih10-sans px-6 py-10" aria-label="Neon glow border image hover demo">
<div class="grid w-full max-w-195 gap-5 grid-cols-1 sm:grid-cols-3">
<article style="--glow:oklch(0.82 0.15 320); --glow-dim:oklch(0.82 0.15 320/0.25); --glow2:oklch(0.79 0.13 205)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-gpu/600/600'),linear-gradient(135deg,oklch(0.16_0.06_305),oklch(0.28_0.14_305),oklch(0.42_0.2_302))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Cipher X9 GPU</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">24GB GDDR7 · Ray Tracing</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 98 / 100 Performance</p>
</div>
</article>
<article style="--glow:oklch(0.79 0.13 205); --glow-dim:oklch(0.79 0.13 205/0.25); --glow2:oklch(0.88 0.13 150)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-oled/600/600'),linear-gradient(135deg,oklch(0.17_0.04_230),oklch(0.3_0.07_230),oklch(0.42_0.1_232))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Horizon 4K OLED</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">240Hz · 1ms GTG · HDR</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 96 / 100 Visuals</p>
</div>
</article>
<article style="--glow:oklch(0.88 0.13 150); --glow-dim:oklch(0.88 0.13 150/0.25); --glow2:oklch(0.82 0.15 320)" class="group relative rounded-[14px] border border-[oklch(1_0_0/0.06)] transition-[box-shadow,border-color] duration-400 ease-tih10 hover:border-[var(--glow)] hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)] motion-reduce:transition-none">
<div class="relative aspect-square grid place-items-center overflow-hidden rounded-t-[13px] text-[var(--glow)] bg-[image:url('https://picsum.photos/seed/tih10-keyboard/600/600'),linear-gradient(135deg,oklch(0.16_0.04_160),oklch(0.3_0.08_162),oklch(0.38_0.09_163))] bg-cover bg-center bg-no-repeat before:content-[''] before:absolute before:top-2 before:left-2 before:w-4 before:h-4 before:border-t-2 before:border-l-2 before:border-current before:opacity-0 before:transition-opacity before:duration-400 after:content-[''] after:absolute after:bottom-2 after:right-2 after:w-4 after:h-4 after:border-b-2 after:border-r-2 after:border-current after:opacity-0 after:transition-opacity after:duration-400 group-hover:before:opacity-100 group-hover:after:opacity-100 motion-reduce:before:transition-none motion-reduce:after:transition-none">
</div>
<div class="px-4 py-3.5 rounded-b-[13px] bg-[oklch(0_0_0/0.3)]">
<h3 class="text-[13px] font-bold text-tih10-text">Spectra 75% MK</h3>
<p class="mt-0.75 text-[11px] text-tih10-muted">Optical · Per-key RGB</p>
<p class="mt-2 text-xs font-extrabold bg-clip-text text-transparent bg-linear-[90deg,var(--glow),var(--glow2)]">★ 94 / 100 Feel</p>
</div>
</article>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tih10-bg: #030308;
--color-tih10-bg: oklch(0.08 0.008 285);
--color-tih10-text: #f1f5f9;
--color-tih10-text: oklch(0.96 0.005 250);
--color-tih10-muted: #64748b;
--color-tih10-muted: oklch(0.58 0.035 255);
--font-tih10-sans: 'Space Grotesk', system-ui, sans-serif;
--ease-tih10: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
/* 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-10 {
width: 100%;
min-height: 100svh;
}
.tih-10 ::selection {
background: oklch(0.82 0.15 320);
color: #000;
}
```How this works
The glow is data-driven. Each card sets two properties inline and the class list is identical:
<article style="--glow:oklch(0.82 0.15 320); --glow-dim:oklch(0.82 0.15 320/0.25)"
class="hover:shadow-[0_0_0_1px_var(--glow),0_0_20px_var(--glow),0_0_60px_var(--glow-dim)]">The CSS version needs a --card--1:hover rule per colour. Here the colour is content and the effect is markup, which is the correct split for a CMS-driven card grid.
Pseudo-elements are variants. The brackets need no extra boxes:
class="before:content-[''] before:absolute before:top-2 before:left-2
before:w-4 before:h-4 before:border-t-2 before:border-l-2
before:border-current before:opacity-0
group-hover:before:opacity-100"box-shadow, not drop-shadow. Both can glow; only box-shadow avoids creating a stacking context and stays cheap on the compositor. The port keeps that choice and states it in the class list.
Make it yours
- Glow colour per card: edit the inline
--glow/--glow-dimpair. - Interior rim light: append
,inset_0_0_20px_var(--glow-dim)inside the same arbitrary shadow. - Smaller ambient on mobile:
sm:hover:shadow-[…60px…]with a 30px base value. - Bracket size: the
before:w-4 before:h-4pair, andbefore:border-t-4for a heavier corner. - Add a pulse with an
--animate-tih10-pulse@themeentry andgroup-hover:animate-tih10-pulse.
Gotchas — read before shipping
- Arbitrary shadows with multiple layers need underscores for every space and commas between layers — one stray space and the whole utility is dropped silently.
before:content-['']is mandatory. Without it the pseudo-element does not generate and the brackets never appear.- Very large spreads (>100px) are real paint cost with many cards visible; clip with an
overflow-hiddenancestor if the grid is long. bg-clip-text text-transparentneeds a background on the same element and fails to an invisible line if the gradient utility is dropped — keep atext-fallback in print styles.- The card's
overflow-hiddenwould clip its own glow; the clip lives on the inner frame instead. Check this when refactoring. - 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+ |
box-shadow is universal; the gradient-text technique relies on background-clip: text, which is broadly but not universally supported — keep a solid-colour fallback.