CSS anchor positioning + Popover API

Constellation Map

Tooltip positioning logic that took 200+ lines of floating-UI JavaScript is now four lines of CSS, with browser-managed dismiss, stacking and keyboard handling.

Use it for: Interactive maps · onboarding tours · data tooltips

Teach_ing

Physics, chemistry, biology, neuropsychology — half a decade of igniting students.

Koach_ing

1:1 transformation. The G.E.M. framework, from diagnostic to lift-off.

Perform_ing

TEDx: The 3 Laws of Emotion. Flowcus Pocus. Two decades on stage.

Invent_ing

The Philosopher's Pen_Cil — writing tools for states of flow.

click a star ✦ tooltips are CSS-anchored native popovers — zero positioning JS

The complete source

This is the exact file rendering the demo above — a single self-contained React client component with its styles inline. Copy or download it, drop it into any React / Next.js project, and it runs. No extra dependencies.

anchors.jsx
1"use client";
2
3/* ============================================================
4 CONSTELLATION MAP — CSS Anchor Positioning + the Popover API.
5 Supported in all major browsers as of late 2025.
6 Each star is an anchor; its tooltip tethers itself with
7 position-area + position-try fallbacks. The popovers open and
8 close with ZERO JavaScript — the `popovertarget` attribute
9 does the wiring, the browser handles dismiss & stacking.
10 ============================================================ */
11
12const STARS = [
13 { id: "teach", x: 18, y: 30, label: "Teach_ing", info: "Physics, chemistry, biology, neuropsychology — half a decade of igniting students." },
14 { id: "koach", x: 42, y: 62, label: "Koach_ing", info: "1:1 transformation. The G.E.M. framework, from diagnostic to lift-off." },
15 { id: "perform", x: 66, y: 26, label: "Perform_ing", info: "TEDx: The 3 Laws of Emotion. Flowcus Pocus. Two decades on stage." },
16 { id: "invent", x: 84, y: 58, label: "Invent_ing", info: "The Philosopher's Pen_Cil — writing tools for states of flow." },
17];
18
19export default function Anchors() {
20 return (
21 <div className="anchor-wrap">
22 <style>{`
23 .anchor-wrap {
24 position: relative; height: 60svh; border-radius: 24px;
25 border: 1px solid rgba(255,255,255,.15); overflow: clip;
26 background:
27 radial-gradient(circle at 20% 80%, rgba(124,58,237,.25), transparent 50%),
28 radial-gradient(circle at 80% 20%, rgba(6,182,212,.2), transparent 50%),
29 #0a0a12;
30 }
31 .anchor-star {
32 position: absolute; translate: -50% -50%;
33 width: 22px; height: 22px; border-radius: 50%;
34 background: radial-gradient(circle at 35% 35%, #fff, #ffa500 60%, transparent);
35 box-shadow: 0 0 18px 4px rgba(255,165,0,.55);
36 border: none; cursor: pointer;
37 animation: star-pulse 2.4s ease-in-out infinite;
38 }
39 .anchor-star:hover { animation-play-state: paused; scale: 1.3; }
40 @keyframes star-pulse { 50% { box-shadow: 0 0 28px 8px rgba(255,165,0,.8); } }
41
42 /* anchor names — one per star */
43 ${STARS.map(
44 (s) => `
45 #star-${s.id} { anchor-name: --star-${s.id}; left: ${s.x}%; top: ${s.y}%; }
46 #tip-${s.id} {
47 position-anchor: --star-${s.id};
48 position-area: top;
49 position-try-fallbacks: bottom, left, right;
50 margin: 12px;
51 }`
52 ).join("\n")}
53
54 /* the tooltips are native popovers — no JS open/close */
55 .anchor-tip {
56 position: fixed; /* required for anchor positioning */
57 width: min(34ch, 70vw);
58 border: 1px solid rgba(255,255,255,.25); border-radius: 16px;
59 background: rgba(16,16,28,.92); color: #fff;
60 padding: 1.6rem; font-size: 1.4rem; line-height: 1.6;
61 backdrop-filter: blur(8px);
62 box-shadow: 0 18px 50px rgba(0,0,0,.5);
63 }
64 .anchor-tip::backdrop { background: transparent; }
65 .anchor-tip h4 { font-size: 1.7rem; font-weight: 800; margin-bottom: .6rem; color: #ffa500; }
66 .anchor-tip p { color: rgba(255,255,255,.82); }
67
68 /* connecting constellation lines (decorative) */
69 .anchor-lines { position: absolute; inset: 0; pointer-events: none; opacity: .35; }
70
71 .anchor-help {
72 position: absolute; bottom: 12px; left: 50%; translate: -50% 0;
73 font-size: 1.25rem; color: rgba(255,255,255,.55);
74 background: rgba(0,0,0,.4); padding: .5rem 1.4rem; border-radius: 999px;
75 }
76 `}</style>
77
78 <svg className="anchor-lines" viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
79 <polyline
80 points={STARS.map((s) => `${s.x},${s.y}`).join(" ")}
81 fill="none"
82 stroke="rgba(255,255,255,.5)"
83 strokeWidth="0.18"
84 strokeDasharray="1.5 1.2"
85 />
86 </svg>
87
88 {STARS.map((s) => (
89 <button
90 key={s.id}
91 id={`star-${s.id}`}
92 className="anchor-star"
93 popoverTarget={`tip-${s.id}`}
94 aria-label={`Open ${s.label}`}
95 />
96 ))}
97
98 {STARS.map((s) => (
99 <div key={s.id} id={`tip-${s.id}`} className="anchor-tip" popover="auto">
100 <h4>{s.label}</h4>
101 <p>{s.info}</p>
102 </div>
103 ))}
104
105 <p className="anchor-help">
106 click a star ✦ tooltips are CSS-anchored native popovers — zero positioning JS
107 </p>
108 </div>
109 );
110}
111