🔄 Spin360
★ Star on GitHub

360° product views in one HTML tag

Spin360 is a tiny web component that turns an image sequence into a smooth, draggable 360° product view. No framework, no dependencies, no build step.

0 dependencies< 5 KB gzippedTouch · mouse · keyboardLazy loadingSprite sheets
Get started View on GitHub →
0°

Install

Load the module, from a CDN or from your own copy, and add the tag:

<script type="module" src="https://cdn.jsdelivr.net/gh/ahmettasdemirusa/spin360@v1.0.0/spin360.js"></script>

<spin-360 src="/images/mug/{i}.webp" frames="36" pad="2" alt="Ceramic mug"></spin-360>

{i} is replaced by the frame number. pad="2" turns it into 00, 01 … 35. The viewer takes the aspect ratio of your images and the width of its container.

One file, one request: sprite sheets

Put every frame in a single image, in a grid, and tell Spin360 how many columns it has. This one is a 6 × 6 grid of 36 frames, about 100 KB in total.

<spin-360 sprite="mug-sprite.webp"
          frames="36" columns="6"></spin-360>

Attributes

AttributeWhat it does
srcURL pattern for the frames, with {i} for the frame number
padZero-pad the frame number to this many digits
sprite · columnsUse a single sprite-sheet image instead of separate files
framesNumber of frames (default 36)
startFrame to show first
autoplay · speedTurn on its own at speed frames per second (default 12). Stops on first interaction, and never starts for users who prefer reduced motion.
drag-speedDrag sensitivity multiplier (default 1: one full turn per viewer width)
reverseInvert the drag and arrow-key direction
no-loopStop at the first and last frame instead of wrapping around
no-inertia · no-hintTurn off coasting after a flick, or the "Drag to rotate" hint
eagerLoad immediately instead of when the viewer scrolls near the viewport
altAccessible label for screen readers

JavaScript API

const viewer = document.querySelector('spin-360');

viewer.goTo(9);          // jump to a frame
viewer.next(); viewer.prev();
viewer.play(); viewer.pause();
viewer.frame;            // current frame

viewer.addEventListener('spin360:change', (e) =>
  console.log(e.detail.frame, e.detail.angle));
viewer.addEventListener('spin360:load', () => {});

// Switch colorway: the angle is kept
viewer.setAttribute('src', '/img/blue/{i}.webp');

Accessible by default

The viewer is a focusable role="slider" that announces its angle, e.g. "90°".

KeyAction
← → ↑ ↓Rotate one frame
Page Up / DownRotate 45°
Home / EndFirst / last frame
SpacePlay / pause

Style it with CSS custom properties: --spin360-accent, --spin360-focus, --spin360-hint-bg, --spin360-hint-color, or with ::part(canvas|progress|hint).

Part of the 3D Web series