Skip to content
animorio
IT
All components

The thin drum select

Pickers, Text, TransitionsGSAP, CSS onlyMediumCompressed weight: Demo 6.8 KBGSAP 28 KBFreeDownload the zip

A select in the minimal style, all on one thin line: the words Ship to, the chosen country and the delivery days. Opened, the other countries roll out above and below the value like the faces of a drum, smaller and lighter as they turn away; the one in the middle gains weight and width. It turns with the wheel, a finger or the keys; choosing, the drum rolls shut on the country and the new value lands on the line one pixel too low, then settles.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The thin drum select</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- a select on a thin line. Opened, the options roll out above and below the value like the faces of a drum;
         the one in the middle gains weight, and choosing rolls the drum shut on it. The options are drawn by the
         script from the list below -->
    <div class="frame" data-frame>
    <div class="sel" data-select>
      <span class="sel__label" id="sel-label">Ship to</span>
      <button class="sel__field" type="button" role="combobox" aria-haspopup="listbox" aria-expanded="false"
              aria-controls="sel-list" aria-labelledby="sel-label sel-value" data-field>
        <span class="sel__value" id="sel-value"><span class="sel__value-in" data-value>Italy</span></span>
      </button>
      <span class="sel__days" aria-hidden="true"><span class="sel__days-in" data-days>2–3 days</span></span>
      <svg class="sel__chev" viewBox="0 0 14 14" aria-hidden="true"><path d="M3 5.5 7 9.5 11 5.5" /></svg>
      <div class="sel__drum" id="sel-list" role="listbox" aria-labelledby="sel-label" data-drum hidden>
        <div class="sel__roll" data-roll></div>
      </div>
      <span class="sel__band sel__band--top" aria-hidden="true"></span>
      <span class="sel__band sel__band--bottom" aria-hidden="true"></span>
      <span class="sel__line" aria-hidden="true" data-line></span>
      <span class="sel__ink" aria-hidden="true" data-ink></span>
    </div>
    </div>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

17 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The thin drum select” from Animorio and fit it into my site

What it does

On a white page sits a select at most 380 pixels wide and 60 high, all on one thin black line: on the left the words Ship to in grey capitals, then the chosen country (Italy) in a solid grotesque, on the right the delivery days (2–3 days) and a thin arrow. Pressing it, the arrow turns over, a vermilion line draws itself along the line from left to right and the other countries roll out above and below the value like the faces of a drum, on a spring that goes just past and comes back: the near ones are wide and almost black, the far ones narrower, lighter and paler, bent backwards on the curve. Two very thin grey lines frame the middle face, which is always the boldest and the widest: as the drum turns, each country gains weight and width coming into the middle and loses them going out, and the delivery days on the right roll over in their slot. The drum turns with the wheel, one face at a time; with a drag, of the mouse or a finger, and flung it stops on a face by itself; with the arrow keys, Page Up and Down, Home and End, and by typing the first letters of a country. A click on a country brings it to the middle, a click on the middle one chooses it. Choosing, the drum rolls shut on the country, the vermilion line pulls back to the right and the new value drops on to the line, one pixel too low, and settles. Esc or a click outside close it without a change. While nobody touches it, the select opens, turns and chooses by itself.

How it works

The drum in CSS 3D

Each country is a face turned STEP degrees for its distance from the middle (rotateX) and pushed out by the drum's radius (translateZ); the roll is pushed back by the same radius, so the middle face stays exactly where the field's value sits. The radius comes from the height of a face so that two neighbouring faces just touch; faces turned past 89 degrees are not drawn.

Weight and width from the distance

On every frame each face gets its font-variation-settings: wght from LIGHT to HEAVY and wdth from 84 to 100 depending on how near the middle it is, and an opacity that follows the cosine of its angle. The middle face has the same type as the field's value: opening, the value hides behind it without the change showing.

A spring to turn

The drum's position is a number with decimals that a spring pulls towards the right face (SPRING and DAMP, with the time step kept under 1/30 of a second). A drag holds it, giving way less and less past the ends; let go, the face it would stop on with the speed it had is chosen and the spring takes it there.

Opening and closing

Opening is a single number from 0 to 1 that multiplies the angles: at 0 every face is squeezed behind the value, at 1 the drum is open; GSAP takes it up with back.out, which goes just past. Closing takes it back to 0 while the drum comes round to the chosen face, then the new value drops on to the line LAND pixels too low and settles.

A real select

The field is a button with role combobox, aria-expanded, aria-controls and aria-activedescendant; the list is a listbox of options with aria-selected. The focus always stays on the field: arrows, Page Up and Down, Home and End turn the drum, Enter and Space choose, Tab chooses and moves on, Esc closes without a change, letters typed in a row look for the country.

Values to change

NameFileDefaultWhat it changes
STARTscript.js6The country chosen when the page opens, by its place in the list.
STEPscript.js22The degrees between two faces of the drum: fewer degrees, a bigger drum with more countries in view.
SPRINGscript.js190How hard the spring pulls the drum on to its face.
DAMPscript.js21How much the spring holds the drum back: less, and it swings further past.
OPEN_TIMEscript.js0.6The seconds the drum takes to roll out.
CLOSE_TIMEscript.js0.34The seconds the drum takes to roll shut.
LANDscript.js1How many pixels too low the new value lands before it settles.
HEAVYscript.js760The weight of the middle face.
LIGHTscript.js330The weight of the faces furthest away.

Try them in the Playground

When to use it

For a select with many short options in a clean form: the shipping country at a shop's checkout, the size, the language, the time zone, the category of a request.

On phones

With a finger the drum is dragged and flung; under 420 pixels the type drops to 20 pixels and the delivery days hide, to leave room for long names.

With reduced motion

No turning and no springs: opened, the countries sit in a flat column that fades upwards and downwards and fades in; the drum jumps straight to the right face and the new value does not drop.

Pitfalls

  • The middle face and the field's value must have the same type, the same size and the same position to the pixel: otherwise opening shows a jump. The drum starts at the field's left edge, measured with offsetLeft on every resize.
  • Closing, the spring and the GSAP tween move the same number: the spring is already aiming at the chosen face, so they agree.
  • The focus always stays on the field (a drag puts it back there): a listbox taking the focus would make the select close on blur.

Libraries

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 6.8 KB; the libraries: GSAP 28 KB.

Testing

Tested on 22 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All components