Radial Menu — Free HTML CSS JS Fan-Out Action Snippet

Radial Menu · Navigation · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Trig arc placement
Polar-to-Cartesian spaces items evenly.
Configurable fan
START, SPREAD, and RADIUS shape the arc.
Spring motion
An overshooting easing pops items out.
Staggered cascade
Per-item delays unfurl the menu.
Rotating trigger
Plus turns to a close icon on open.
Hover labels
Tooltips name the icon-only actions.
Click-away and Escape
Standard dismissal.
Accessible trigger
aria-haspopup and aria-expanded.

About this UI Snippet

Radial Menu — Actions That Fan Out on an Arc

Screenshot of the Radial Menu snippet rendered live

The radial menu is the playful action launcher where tapping a central button makes its options spring outward along a circular arc, each landing at an evenly-spaced position around the trigger. It is compact at rest and delightful in motion. This snippet builds it with plain HTML, CSS, and vanilla JavaScript that places the items with a little trigonometry.

Positioning items on an arc

Each action button starts stacked exactly on the trigger and has a precomputed resting position on the arc. For item i, the angle is START + (SPREAD / (count - 1)) * i, converted to radians, and the offset is (cos(angle) * RADIUS, sin(angle) * RADIUS). That standard polar-to-Cartesian conversion spreads the items evenly across a 180° arc at a fixed radius from the center. Because the angles are computed from constants, you change the fan shape — full circle, quarter arc, different radius — just by editing START, SPREAD, and RADIUS.

The spring open and close

Opening toggles an .open class and, for each item, sets a transform to its arc offset at full scale; closing returns every item to translate(0,0) scale(.2) stacked under the trigger. The transition uses an overshooting cubic-bezier(.34, 1.4, .5, 1), so the items spring past their target and settle — the bouncy pop that makes a radial menu feel alive rather than mechanical. The trigger itself rotates the + to a × (135°) on open as a clear affordance.

Staggered emergence

Rather than all items appearing at once, each gets a transition-delay proportional to its index on open (and reversed on close), so they fan out one after another and fold back in sequence. This small cascade reads as the menu unfurling and is the difference between a cheap reveal and a satisfying one.

Hover labels

Each item shows a tooltip label on hover via a small .rm-label that fades in beneath it, so the icon-only buttons remain understandable. The items only become interactive (pointer-events: auto) when the menu is open, so the collapsed stack does not intercept clicks.

Dismissal and accessibility

The menu closes on a click anywhere else (the trigger stops propagation so opening does not immediately self-close) and on Escape. The trigger carries aria-haspopup and an aria-expanded that flips with state, and items are real <button>s, so the control is keyboard- and screen-reader-aware. Wire each item click to its action by reading from the ACTIONS data.

Customizing it

Edit the ACTIONS array to change the options, adjust START/SPREAD/RADIUS to reshape the fan (set SPREAD to 360 for a full ring), retune the spring and stagger, or recolor the trigger and items. Anchor the menu in a corner with a quarter-circle arc for a floating action button. Pair it with a gooey menu or an expanding fab for related launcher patterns.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You do not have to work out the arc placement math and stagger logic by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the angle formula START plus SPREAD divided by count-minus-one times index spaces items evenly across a half-circle, and why the transitionDelay is set to a different multiplier when opening versus closing. The same assistant can help you optimize it — ask whether recalculating every item's dataset.x and dataset.y on every build is necessary or whether it could be memoized once since ACTIONS never changes, and whether the overshooting cubic-bezier easing could cause items to visually collide mid-animation with a tighter RADIUS. It's also useful for extending the menu: ask it to support a full 360-degree ring instead of a half-arc, add keyboard arrow-key navigation between the fanned-out items, or let the trigger be repositioned to any corner of the screen. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a radial (fan-out) action menu in plain HTML, CSS, and JavaScript with no library — a central trigger button that spreads several action buttons along a circular arc when clicked.

Requirements:
- Compute each action item's resting position with polar-to-Cartesian math: for item index i out of N items, the angle equals a START constant plus (a SPREAD constant divided by (N minus 1)) times i, converted to radians, and the offset equals cos(angle) times RADIUS for x and sin(angle) times RADIUS for y — store these as data attributes on each item at build time.
- Items must start stacked directly on top of the trigger at scale 0.2 and fully transparent, with pointer-events disabled while closed.
- Opening the menu must translate every item to its precomputed (x, y) offset at full scale and opacity, using a CSS transition with an overshooting easing curve (a cubic-bezier with a value greater than 1 in one of its control points) so items spring past their final position slightly before settling.
- Give each item a transition-delay proportional to its index so items fan out one after another in sequence on open, and reverse that stagger order on close so they fold back in the opposite sequence.
- The trigger icon itself must rotate (e.g. from a plus to an X shape, via a rotate transform) to indicate open/closed state.
- Close the menu when clicking anywhere outside it or pressing Escape, and make sure clicking the trigger itself does not immediately re-trigger the outside-click handler in the same event.
- Add aria-haspopup and a toggling aria-expanded attribute on the trigger, and implement every action as a real button element so it is keyboard and screen-reader accessible, with a small tooltip label appearing on hover since the buttons are icon-only.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA single round trigger button renders.
  2. 2
    Click the triggerAction items spring out along a half-circle arc.
  3. 3
    Watch the staggerItems fan out one after another with a bounce.
  4. 4
    Hover an itemA tooltip label names the action.
  5. 5
    Dismiss itClick elsewhere or press Escape to fold it back.
  6. 6
    Reshape the fanEdit START, SPREAD, and RADIUS constants.

Real-world uses

Common Use Cases

Floating action buttons
A radial take on an expanding fab.
Quick actions
Fan out edit, share, and delete options.
Canvas and editor tools
Pair with a context menu.
Mobile launchers
A playful cousin of a gooey menu.
Map and media controls
Surface controls around a focal point.
Arc-layout demos
A reference for trig-based item placement.

Got questions?

Frequently Asked Questions

Each item gets an angle of START + (SPREAD / (count - 1)) * index, converted to radians, and an offset of cos(angle)*RADIUS, sin(angle)*RADIUS. That polar-to-Cartesian conversion places them evenly across the arc at a fixed radius. Editing START, SPREAD, and RADIUS reshapes the fan into a full circle, a quarter arc, or any radius.

Opening sets each item transform to its arc offset at full scale, with a transition using an overshooting cubic-bezier(.34,1.4,.5,1). The curve makes items spring slightly past their target and settle, which is the satisfying pop. Closing returns them to a stacked, scaled-down position under the trigger on the same easing.

Each item is given a transition-delay proportional to its index on open, and the order is reversed on close. That stagger makes the items fan out in sequence and fold back in sequence, which reads as the menu unfurling rather than every option blinking in at once.

Each item has a small label that fades in on hover beneath it, so the action is named when you point at it. The items also only become clickable when the menu is open, via pointer-events, so the collapsed stack under the trigger does not intercept clicks.

Compute each item angle and offset from your actions array in render, and keep an open boolean in state that toggles the transforms and stagger delays via inline styles. Add click-away and Escape handlers in a mount effect with cleanup. The spring CSS ports directly. In Tailwind, apply the transforms and transition with arbitrary values driven by the open state.