---
title: 3D Card Ring
description: Photo cards bent around a 3D cylinder that spins with wheel and drag.
category: Gallery
tier: pro
url: https://ui.dimaac.com/components/card-ring-3d
registry: https://api.dimaac.com/v1/ui/r/card-ring-3d.json
registry_auth: Authorization: Bearer <DiMaac licence key>
---

# 3D Card Ring

A ring of photo cards wrapped around a cylinder, drawn on a single 2D canvas with no 3D library. Every card is cut into thin slices that are placed on the cylinder, tilted toward the camera and put in perspective, so the cards really curve; the far side shows their backs and fades into a fog colour that can follow your theme through CSS variables. It turns slowly by itself and whips in when the photos arrive; wheel, drag, touch and the arrow keys spin it, and the spin glides back to the slow turn. The canvas is sharp on retina screens, fits itself to any box, pauses off screen, and stays still (but can still be turned by hand) when the visitor prefers reduced motion.

## Install

This is a Pro component: its source is for buyers of Pro Components, a Templates plan or All-Access, and is not on this page. It installs from the authenticated registry, with the licence key in an environment variable.

1. Merge the registry into components.json (the key is never written into the file):

```json
{
  "registries": {
    "@dimaac-pro": {
      "url": "https://api.dimaac.com/v1/ui/r/{name}.json",
      "headers": { "Authorization": "Bearer ${DIMAAC_LICENSE_KEY}" }
    }
  }
}
```

2. Put the licence key in `.env.local` (keep it out of git; never print or commit it). Ask the owner for it if it isn't set:

```bash
DIMAAC_LICENSE_KEY=your-licence-key
```

3. Add the component:

```bash
npx shadcn@latest add @dimaac-pro/card-ring-3d
```

The registry item is https://api.dimaac.com/v1/ui/r/card-ring-3d.json and answers only with `Authorization: Bearer <licence key>` (or `X-License-Key`). It answers 401 without a key, 403 for a key that isn't valid, and 402 for a key whose purchase doesn't include Pro components (see https://ui.dimaac.com/pricing).

Dependencies:

None: it only needs React 19.

By hand:

Unlock the code on https://ui.dimaac.com/components/card-ring-3d with your licence key, then:

1. It needs nothing but React 19.
2. Copy the component file from the Code panel (once your licence key unlocks it) into components/dimaac/card-ring-3d.tsx.
3. It's styled with Tailwind v4 classes. If that folder sits outside the places Tailwind scans, add it with @source in your CSS.
4. Import it with import { CardRing3d } from "@/components/dimaac/card-ring-3d" and give its parent a size: it fills it.

## Usage

```tsx
import { CardRing3d } from "@/components/dimaac/card-ring-3d";

<CardRing3d images={images} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `images` (required) | `(string \| CardRingItem)[]` | - | The cards, as photo URLs or items with a title. 8 to 16 photos of the same shape look best. |
| `radius` | `number` | `600` | Radius of the cylinder, in pixels (before it is scaled down to fit a small box). |
| `cardWidth` | `number` | `260` | Width of each card along the ring, in pixels. Cards shrink if they don't fit around it. |
| `cardHeight` | `number` | `360` | Height of each card, in pixels. |
| `tilt` | `number` | `10` | How far the camera looks down on the ring, in degrees. 0 is side on. |
| `roll` | `number` | `-10` | How far the whole ring leans to one side, in degrees. |
| `sway` | `number` | `4` | How far the lean sways back and forth by itself, in degrees. 0 keeps it still. |
| `speed` | `number` | `1` | How strongly wheel and drag spin the ring. 1 means a dragged card follows the pointer. |
| `autoRotate` | `number` | `0.6` | How fast the ring turns by itself, in radians a second. 0 stops it when the spin runs out. |
| `friction` | `number` | `0.95` | How much of a spin is kept each frame (at 60 frames a second). Higher glides longer. |
| `perspective` | `number` | `1200` | Distance from the camera to the front cards, in pixels. Smaller is a stronger 3D effect. |
| `fog` | `number` | `0.4` | How much the far side fades into the fog colour. 0 is no fog. |
| `fogColor` | `string` | `"#ebe7e1"` | The colour far cards fade into. Match the background. Any CSS colour, CSS variables too. |
| `backColor` | `string` | `"#d8d4ce"` | The colour of the cards' backs, seen on the far side. Any CSS colour, CSS variables too. |
| `cardColor` | `string` | `"#0b0b0b"` | The card's frame and label background. A plain canvas colour (hex, rgb or hsl). |
| `textColor` | `string` | `""` | The title's colour. A plain canvas colour. Empty picks white or near-black to suit the card colour. |
| `accentColor` | `string` | `"#f26e33"` | The subtitle's colour. A plain canvas colour. |
| `fontFamily` | `string` | `"Syne, sans-serif"` | The labels' font, e.g. "Syne, sans-serif". Load the font on the page yourself. |
| `shadow` | `boolean` | `true` | A soft shadow under the ring. |
| `wheel` | `boolean` | `true` | Spin the ring with the mouse wheel or trackpad (the page doesn't scroll over it then). |
| `label` | `string` | `"Gallery"` | What screen readers call the ring. |
| `className` | `string` | `""` | Extra classes for the outer box. Give it a size (it fills it). |

## Credits

- Portrait: studiomiklus, Lummi (https://www.lummi.ai/photo/striking-portrait-jodiu), Lummi License
- Portrait: Lloyd Creates, Lummi (https://www.lummi.ai/photo/poised-portrait-ooi9b), Lummi License
- Portrait: West Kast, Lummi (https://www.lummi.ai/photo/monochrome-portrait-of-a-young-woman-shb7s), Lummi License
- Portrait: SHIHO, Lummi (https://www.lummi.ai/photo/vibrant-woman-portrait-htofy), Lummi License
- Portrait: Benginur Hajjaj, Lummi (https://www.lummi.ai/photo/calm-portrait-d1zqo), Lummi License
- Portrait: Shaun Duval, Lummi (https://www.lummi.ai/photo/portrait-with-neon-sunglasses-gindg), Lummi License
- Portrait: Dynamic Wang, Lummi (https://www.lummi.ai/photo/profile-portrait-of-woman-xyyue), Lummi License
- Portrait: Amino, Lummi (https://www.lummi.ai/photo/vivid-portrait-on-pink-oxbow), Lummi License
- Portrait: Edita, Lummi (https://www.lummi.ai/photo/striking-portrait-kfent), Lummi License
- Portrait: Steph Meade, Lummi (https://www.lummi.ai/photo/expressive-minimal-portrait-jrfyc), Lummi License

## Source

The source of a Pro component is for buyers of Pro Components, a Templates plan or All-Access. Install it with the commands above, or unlock it on https://ui.dimaac.com/components/card-ring-3d.

## Agent prompt

```text
Add the 3D Card Ring component (<CardRing3d />) from DiMaac UI to this project. It is a Pro component, so its source needs the owner's DiMaac licence key (Pro Components, a Templates plan or All-Access).

Docs: https://ui.dimaac.com/components/card-ring-3d

1. Add the Pro registry to components.json (merge it into "registries"). Don't write the key into the file:
{
  "registries": {
    "@dimaac-pro": {
      "url": "https://api.dimaac.com/v1/ui/r/{name}.json",
      "headers": { "Authorization": "Bearer ${DIMAAC_LICENSE_KEY}" }
    }
  }
}

2. The owner puts their licence key in .env.local (keep it out of git): DIMAAC_LICENSE_KEY=your-licence-key
   Ask them for it if it isn't set. Never print it or commit it.

3. Install it with:
npx shadcn@latest add @dimaac-pro/card-ring-3d

The registry item is https://api.dimaac.com/v1/ui/r/card-ring-3d.json and wants the header "Authorization: Bearer <licence key>".

Then use it like this:
import { CardRing3d } from "@/components/dimaac/card-ring-3d";
<CardRing3d images={images} />

It uses Tailwind v4 classes, so make sure Tailwind scans that folder.
Give its parent a size, keep light and dark mode working and keep its prefers-reduced-motion fallback.
Full index for agents: https://ui.dimaac.com/llms.txt
```
