Anchored positioning
Floating surfaces in Hypermedia Components — tooltips, popovers, hovercards, menus, comboboxes — are placed by shared infrastructure rather than per-component positioning code. Two cooperating pieces keep every surface behaving identically:
hc-anchored.css— the CSS Anchor Positioning path. Mapsdata-side/data-aligntoposition-area(withposition-try-fallbacksto flip at the viewport edge) for.hc-tooltip,.hc-popover, and.hc-hovercard, and renders the optionaldata-arrowpointer.anchor-fallback.js— the JS fallback inside the behaviors. On engines without Anchor Positioning it measures withgetBoundingClientRect, flips on overflow, clamps to the viewport, and keeps tracking on scroll / resize. Shared by the tooltip, popover, hovercard, menu / submenu, navmenu, combobox, and multicombobox behaviors.
Both paths key off the same attributes, so an element is placed identically whichever path the engine takes.
This is internal infrastructure: it ships inside the CSS bundle and the behaviors automatically — there is nothing to install. When you compile a custom bundle from per-component imports, include it once via the granular export:
@import '@hypermedia-components/core/css/hc-anchored';Per-instance attributes
Section titled “Per-instance attributes”| Attribute | Values | Meaning |
|---|---|---|
data-side | top / right / bottom / left | Which side of the trigger the surface opens on. Each component documents its own default. |
data-align | start / center / end | Alignment along the cross axis (default center). |
data-arrow | (boolean) | Renders a small pointer on the anchor-facing edge. |
<button class="hc-button" type="button" popovertarget="filters">Filter</button>
<div id="filters" class="hc-popover" popover data-side="right" data-align="start" data-arrow> Opens to the inline-end, top-aligned, with a pointer.</div>The component pages show the defaults and live demos:
Tooltip (opens above),
Popover
(browser-centred until you add data-side), and
Hovercard (opens below).
Shared knobs
Section titled “Shared knobs”Each component sets these custom properties on its own surface; override them per component (or per instance) to tune the shared mechanics:
| Custom property | Default | Meaning |
|---|---|---|
--hc-anchored-offset | 0.5rem | Gap between the trigger and the surface. |
--hc-anchored-arrow-size | 0.5rem | Size of the data-arrow pointer square. |
--hc-anchored-arrow-border | transparent | Border color of the arrow’s exposed edges (match the surface border). |
/* Tighter tooltips, larger arrow */.hc-tooltip { --hc-anchored-offset: 0.25rem; --hc-anchored-arrow-size: 0.625rem;}How the two paths cooperate
Section titled “How the two paths cooperate”- With CSS Anchor Positioning,
hc-anchored.cssresolvesdata-side/data-alignto aposition-areaand letsposition-try-fallbacks: flip-block | flip-inlinehandle viewport collisions — no JS runs for placement. - Without it, the behavior detects the gap
(
CSS.supports('anchor-name', '--x')) and positions the surface from JS: same side / alignment semantics, flip on overflow, a final clamp so the surface can never sit fully off-screen, and scroll / resize tracking while open. Geometry is computed in physicaltop/leftfromgetBoundingClientRect, so right-to-left pages place correctly (the inline axis flips withdir="rtl"). - The
data-arrowpointer is plain CSS and renders on both paths.