What's included
A carousel of photographs where every image carries clickable points: open a point and a card appears beside it with a title, a price, a description and a link. Below the image, a rail of thumbnails acts as the view selector. Two files, a stylesheet and a script — no dependencies, no build step, no external requests.
A hotspot is a browser <details>: it opens, closes, is driven from the keyboard and exposes its state without anything having been rewritten. The script only projects each point onto the photo, from its coordinates.
Features
-
Points positioned in percentages —
data-xetdata-yon each point, and it lands on the same spot of the image whatever the size of the frame. - The card stays inside the frame — it opens to the right of the point, moves to the left if there isn't room, and slides vertically so it never overflows.
- Full keyboard support — a single tab stop for the thumbnails, the arrow keys to change view, Home and End to reach either end, Enter to open a point, Escape to close it and hand the focus back.
- Works without JavaScript — the frame becomes a native scroller, the thumbnails go back to being anchors, and the points leave the photo to line up beneath the view, still openable.
- One variable for the scale — every measurement derives from the text size: the point, the halo, the arrows, the rail and the card all follow together.
- Optional auto-advance — off by default; when asked for, it pauses on hover, on focus, on an open card, on a hidden tab, and brings its own play/pause button.
Dropping it into a page
Two files to load, then the markup:
<link rel="stylesheet" href="hotspot-carousel.css">
<script src="hotspot-carousel.js" defer></script>
<section class="hotspot-carousel" aria-label="Our rooms">
<div class="hotspot-carousel__viewport">
<article class="hotspot-carousel__slide" id="vue-1">
<img class="hotspot-carousel__image" src="salon.webp" alt="Living room">
<div class="hotspot-carousel__hotspots">
<details class="hotspot-carousel__hotspot" data-x="78" data-y="28">
<summary class="hotspot-carousel__pin">…</summary>
<div class="hotspot-carousel__panel">…</div>
</details>
</div>
</article>
</div>
</section>
The component installs itself on page load: it picks up every
.hotspot-carousel on the page, including those inserted later. The full markup — counter, arrows, thumbnail rail — is in the README and in the demo.
What you should know
- The photos shipped are the ones from the mock-up. They come from the public demo used as the reference, and their licence isn't established. They're there so the reproduction can be checked to the pixel: replace them with your own before publishing anything. The README says so again, with the list of files.
-
A position is data, not a class.
That's why the script is needed to place the points on the image: the site's strict security policy forbids the
styleattribute that would carry the coordinates. Without the script, the points don't disappear — they tuck themselves beneath the view. -
No inline styles, no inline scripts. The component honours the site's strict security policy, and never uses
innerHTML: card text coming out of a database can't inject a tag. - The design comes from elsewhere. The proportions and the motion follow those of a commercial Framer component, measured to the pixel and to the millisecond on its live site. The code itself is original: nothing was taken from its implementation.
Take it, open it, break it.
This component is free. The full library — the templates and the other components — comes with the subscription, alongside the course.
Immediate access · No commitment · Cancel in one click