Arc gallery
Picture cards on the rim of a wide wheel that you drag, flick, scroll sideways or step with the arrow keys; the front one opens full size.
- enhancer
- gallery
- images
- drag
- wheel
- lightbox
- since 0.2
Background Studio: tune it below, then copy the code
Your system asks for reduced motion: the demo shows its final state and nothing moves.
Live demo
Arc gallery example
Code
It follows the controls above: change an option and the code changes with it.
<link rel="stylesheet" href="/axi0/motion/motion.css?v=6">
<script src="/axi0/motion/motion.js?v=10" defer></script>
<div data-motion="arc-gallery" aria-label="Places">
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%231d1033'/%3E%3Cstop offset='1' stop-color='%23f08a4b'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='102' cy='112' r='26' fill='%23ffd27a'/%3E%3Cpath d='M0 212 Q37 244 75 211 T150 223 T225 203 T300 212 V400 H0Z' fill='%237a3b52'/%3E%3Cpath d='M0 264 Q37 304 75 231 T150 263 T225 239 T300 264 V400 H0Z' fill='%234a2440'/%3E%3Cpath d='M0 323 Q37 290 75 305 T150 330 T225 301 T300 323 V400 H0Z' fill='%2324132b'/%3E%3C/svg%3E" alt="A low sun over three rows of dunes at dusk" width="300" height="400"><figcaption>Afterglow</figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%230b2340'/%3E%3Cstop offset='1' stop-color='%235fa8d3'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='162' cy='105' r='29' fill='%23f4f1de'/%3E%3Cpath d='M0 204 Q37 167 75 180 T150 191 T225 185 T300 204 V400 H0Z' fill='%232f5d7c'/%3E%3Cpath d='M0 266 Q37 241 75 241 T150 255 T225 245 T300 266 V400 H0Z' fill='%231d3f5a'/%3E%3Cpath d='M0 332 Q37 359 75 313 T150 330 T225 313 T300 332 V400 H0Z' fill='%230f2638'/%3E%3C/svg%3E" alt="A pale moon over a calm blue harbor" width="300" height="400"><figcaption>Harbor</figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%230f2b1d'/%3E%3Cstop offset='1' stop-color='%237fb685'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='188' cy='130' r='23' fill='%23f2e8cf'/%3E%3Cpath d='M0 219 Q37 196 75 217 T150 226 T225 216 T300 219 V400 H0Z' fill='%233a6b47'/%3E%3Cpath d='M0 274 Q37 239 75 258 T150 286 T225 240 T300 274 V400 H0Z' fill='%2324492f'/%3E%3Cpath d='M0 322 Q37 291 75 299 T150 320 T225 313 T300 322 V400 H0Z' fill='%23132a1b'/%3E%3C/svg%3E" alt="Green hills rolling away under a soft sun" width="300" height="400"><figcaption>Meadow</figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%232b1055'/%3E%3Cstop offset='1' stop-color='%23d53a9d'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='62' cy='86' r='26' fill='%23ffdd99'/%3E%3Cpath d='M0 213 Q37 236 75 208 T150 219 T225 210 T300 213 V400 H0Z' fill='%237e3aa1'/%3E%3Cpath d='M0 274 Q37 308 75 257 T150 273 T225 261 T300 274 V400 H0Z' fill='%234a2071'/%3E%3Cpath d='M0 339 Q37 361 75 319 T150 337 T225 335 T300 339 V400 H0Z' fill='%23200b3a'/%3E%3C/svg%3E" alt="Purple ridges under a pink sunset" width="300" height="400"><figcaption>Violet hour</figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%23f6a04d'/%3E%3Cstop offset='1' stop-color='%23ffd8a8'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='175' cy='105' r='31' fill='%23fff7ea'/%3E%3Cpath d='M0 201 Q37 235 75 180 T150 190 T225 189 T300 201 V400 H0Z' fill='%23d9824a'/%3E%3Cpath d='M0 265 Q37 238 75 252 T150 277 T225 249 T300 265 V400 H0Z' fill='%23a65a2e'/%3E%3Cpath d='M0 324 Q37 292 75 319 T150 325 T225 324 T300 324 V400 H0Z' fill='%235c2f17'/%3E%3C/svg%3E" alt="Orange desert ridges at noon" width="300" height="400"><figcaption>High desert</figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%2310141f'/%3E%3Cstop offset='1' stop-color='%233c4f76'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='108' cy='109' r='22' fill='%23e6e9f2'/%3E%3Cpath d='M0 206 Q37 228 75 200 T150 198 T225 200 T300 206 V400 H0Z' fill='%232a3550'/%3E%3Cpath d='M0 274 Q37 254 75 272 T150 280 T225 259 T300 274 V400 H0Z' fill='%231b2338'/%3E%3Cpath d='M0 324 Q37 287 75 321 T150 320 T225 298 T300 324 V400 H0Z' fill='%230d111c'/%3E%3C/svg%3E" alt="Dark peaks under a moonlit sky" width="300" height="400"><figcaption>Night peaks</figcaption></figure>
<figure><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='400' viewBox='0 0 300 400'%3E%3ClinearGradient id='s' x2='0' y2='1'%3E%3Cstop stop-color='%23a1d6e2'/%3E%3Cstop offset='1' stop-color='%23f1f1f2'/%3E%3C/linearGradient%3E%3Crect width='300' height='400' fill='url(%23s)'/%3E%3Ccircle cx='236' cy='83' r='31' fill='%23ffffff'/%3E%3Cpath d='M0 209 Q37 248 75 173 T150 196 T225 171 T300 209 V400 H0Z' fill='%237fb3c8'/%3E%3Cpath d='M0 268 Q37 291 75 253 T150 257 T225 259 T300 268 V400 H0Z' fill='%234f8aa3'/%3E%3Cpath d='M0 320 Q37 341 75 315 T150 315 T225 303 T300 320 V400 H0Z' fill='%232c5d73'/%3E%3C/svg%3E" alt="Icy blue hills by a frozen lake" width="300" height="400"><figcaption>Frozen lake</figcaption></figure>
</div>
import { ArcGallery } from "./motion/react/ArcGallery";
<ArcGallery>Your content</ArcGallery>
<script setup lang="ts">
import ArcGallery from "./motion/vue/ArcGallery.vue";
</script>
<template>
<ArcGallery>Your content</ArcGallery>
</template>
const el = document.querySelector("#title");
el.dataset.motion = "arc-gallery";
The wrappers: ArcGallery.tsx (React, TypeScript) and ArcGallery.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.
Options
| Attribute | Default | What it does |
|---|---|---|
data-motion-bend | 3 | how strongly the row curves (0: a straight row) |
data-motion-gap | 34 | space between cards |
data-motion-label | Gallery | the name read out when the element has no aria-label |
Accessibility
- The gallery is a labeled region; each card is a button named by its caption and place ("Harbor, 2 of 7"). Tab enters once; Left and Right arrows (Home, End) turn the wheel and move focus with it; Enter on the front card opens it full size, on another card brings it to the front. - The viewer is the browser's own modal dialog (focus kept inside, Escape closes, focus comes back). - Dragging, flicking and sideways scrolling turn it too; a plain vertical wheel still scrolls the page. - Reduced motion turns the wheel in one step. Reduced motion shows every state at once, with no movement, and stops anything that would move on its own. Frame loops and CSS animations pause off screen and in hidden tabs. Only transform, opacity and paint animate, so nothing around it moves.
Size
arc-gallery.js is 2.0 KB gzip, with components-kit.js 3.9 KB it needs. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.