8pt

Hover Preview

Hover Preview•Text
Overview

Hover a keyword in body text and a preview card floats out next to the pointer. The card content is drawn in pure CSS.

Plain HTML, CSS and a little vanilla JS, with no framework dependency. Copy the prompt into Claude Code, Cursor, Trae or Codex and the model adds Hover Preview to your project in your colors.

Where to use it

Animated headlines, testimonials, emphasis copy and large-type layouts.

Install

With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.

$ npm i -g @8pt-dev/cli && 8pt add hover-preview
mcp › Use 8pt MCP to call get_component("hover-preview")

Code

Source for Hover Preview. Motion uses only transform and opacity and respects the Reduce motion setting.

<div class="x-hp">
  <p>Good UI starts with <a data-k="grid">grid systems</a>, uses <a data-k="type">typography</a> to build hierarchy, then <a data-k="ease">motion curves</a> to bring it to life.</p>
  <div class="x-hp__card" aria-hidden="true">
    <div class="x-hp__art" data-art="grid"></div>
    <div class="x-hp__art" data-art="type">Aa</div>
    <div class="x-hp__art" data-art="ease"><svg viewBox="0 0 100 60"><path d="M4 56 C 44 56, 50 4, 96 4" fill="none" stroke="currentColor" stroke-width="2.5"/></svg></div>
  </div>
</div>
.x-hp{position:relative;width:min(460px,100%);color:var(--d-fg,#fff)}
.x-hp p{margin:0;font:500 clamp(17px,2.2vw,22px)/1.7 var(--d-font,system-ui,sans-serif);letter-spacing:-.01em;color:var(--d-muted,#a0a0ab)}
.x-hp a{color:var(--d-fg,#fff);font-weight:700;text-decoration:underline;text-decoration-color:color-mix(in srgb,var(--d-accent,#4D74FF) 70%,transparent);text-underline-offset:5px;cursor:default}
.x-hp__card{position:absolute;left:0;top:0;width:180px;height:120px;border-radius:14px;overflow:hidden;background:#0c0c14;border:1px solid rgba(255,255,255,.12);box-shadow:0 24px 50px -20px rgba(0,0,0,.7);opacity:0;pointer-events:none;transform:translate(0,0) scale(.9);transition:opacity .2s;will-change:transform;z-index:3}
.x-hp__card.on{opacity:1}
.x-hp__art{position:absolute;inset:0;display:none;place-items:center;color:#fff}
.x-hp__art.on{display:grid}
.x-hp__art[data-art=grid]{background:linear-gradient(#4D74FF33 1px,transparent 1px) 0 0/16px 16px,linear-gradient(90deg,#4D74FF33 1px,transparent 1px) 0 0/16px 16px,radial-gradient(circle at 30% 30%,#4b3bff,#0c0c14 70%)}
.x-hp__art[data-art=type]{font:700 64px/1 Georgia,serif;background:linear-gradient(135deg,#1b1b2a,#0c0c14)}
.x-hp__art[data-art=ease]{padding:18px;background:linear-gradient(135deg,#0d2230,#0c0c14);color:#7cf3ff}
.x-hp__art svg{width:100%;height:100%}
const init = (root) => {
  const box = root.querySelector('.x-hp'), card = box.querySelector('.x-hp__card'), arts = card.querySelectorAll('.x-hp__art');
  let x = 0, y = 0, tx = 0, ty = 0, s = .9, ts = .9, raf = 0;
  const tick = () => {
    x += (tx - x) * .2; y += (ty - y) * .2; s += (ts - s) * .2;
    card.style.transform = `translate(${x}px, ${y}px) scale(${s})`;
    raf = Math.abs(tx - x) + Math.abs(ty - y) + Math.abs(ts - s) > .05 ? requestAnimationFrame(tick) : 0;
  };
  box.querySelectorAll('a').forEach(a => {
    a.addEventListener('pointerenter', () => { arts.forEach(el => el.classList.toggle('on', el.dataset.art === a.dataset.k)); card.classList.add('on'); ts = 1; });
    a.addEventListener('pointerleave', () => { card.classList.remove('on'); ts = .9; });
  });
…
Subscribe to Builder to see the full source.See pricing

More text components

View all

Text Scramble

Typewriter Heading

More components

View all

AI Prompt Composer

Film Strip Carousel

Auto Tab Showcase

Media Bento Grid

Agent Chat Window

Model Pill Marquee

Director Art Cards

Mac File Window

Keep exploring