Mesh Gradient Background
Three blurred radial pools over an opaque base - a mesh section that never has to fight its own text for contrast.
6 個のフレームワーク初級
A card whose radial glow follows the pointer - custom properties do the tracking, opacity does the reveal.
<!--
The one place this category genuinely needs JavaScript: CSS cannot read the
pointer. The script only writes two custom properties - no classes toggle,
no layout runs. The reveal itself is a pure-CSS opacity fade on hover, which
means the spotlight simply never exists for touch and keyboard users: the
card must read complete without it.
-->
<div
id="spotlight-card"
class="group relative w-full max-w-sm overflow-hidden rounded-2xl border border-gray-200 bg-white p-6 dark:border-gray-800 dark:bg-gray-900"
>
<div
class="pointer-events-none absolute inset-0 bg-[radial-gradient(240px_circle_at_var(--spot-x,50%)_var(--spot-y,50%),rgba(59,130,246,0.16),transparent_70%)] opacity-0 transition-opacity duration-300 group-hover:opacity-100 motion-reduce:transition-none dark:bg-[radial-gradient(240px_circle_at_var(--spot-x,50%)_var(--spot-y,50%),rgba(96,165,250,0.2),transparent_70%)]"
aria-hidden="true"
></div>
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Hover to light it up</h3>
<p class="mt-2 text-sm leading-relaxed text-gray-600 dark:text-gray-400">
The gradient's centre rides two CSS custom properties; the pointer just
moves them around.
</p>
</div>
<script>
const card = document.getElementById('spotlight-card');
card.addEventListener('pointermove', (event) => {
const rect = card.getBoundingClientRect();
card.style.setProperty('--spot-x', `${event.clientX - rect.left}px`);
card.style.setProperty('--spot-y', `${event.clientY - rect.top}px`);
});
</script>| Prop | 型 | デフォルト | 説明 |
|---|---|---|---|
title必須 | string | - | カードの見出しテキスト。 |
copy | string | - | タイトルの下に表示される本文。 |
className | string | - | ルート要素にマージされる追加クラス。 |
The pointer handler writes two CSS custom properties and nothing else: no `setState`, no class toggles, no layout. Updating a custom property repaints one composited layer, which is why the handler can fire on every `pointermove` without a re-render storm - resist the urge to route the coordinates through React state. The reveal is a pure-CSS opacity fade on `group-hover`, so the spotlight simply never exists for touch and keyboard users; that makes the card’s baseline styling (border, background, text) the real design, and the glow a bonus. Resize the glow via the `240px` in both `radial-gradient()` values and keep its alpha low - it sits under the text, and unlike the mesh it moves, so it must never get strong enough to matter for contrast.