a-track

A scroll-container with snap scrolling, drag gestures, and slider utility functions.

The a-track element is a horizontal or vertical scroll container with built-in support for snap scrolling, drag gestures, keyboard navigation, and looping. It's the foundation for carousels, image galleries, and any scrollable content that benefits from snap points.

Used by Carousel and other sliding components.

Usage

Basic Track

<a-track class="flex overflow-hidden">
  <div class="flex-none w-64">Slide 1</div>
  <div class="flex-none w-64">Slide 2</div>
  <div class="flex-none w-64">Slide 3</div>
</a-track>

With Snap Scrolling

Add the snap attribute to enable snap-to-item behaviour:

<a-track snap class="flex overflow-hidden">
  <div class="flex-none w-full">Slide 1</div>
  <div class="flex-none w-full">Slide 2</div>
  <div class="flex-none w-full">Slide 3</div>
</a-track>

Programmatic Navigation

const track = document.querySelector('a-track');

// Move to a specific slide (0-indexed)
track.moveTo(2);

// Move to next/previous
track.next();
track.prev();

// Get current slide index
console.log(track.current);

Listening for Slide Changes

const track = document.querySelector('a-track');

track.addEventListener('change', (event) => {
  console.log('Current slide:', track.current);
});

Track

A Track is a custom element that provides a interface for scrolling content. It can be used to create carousels, slideshows, and other scrolling elements. It provides functions to go to a specific child element, emits events on changes, and optimizes ux based on input device.

Example


<a-track snap class="flex w-full overflow-visible">
  <div class="flex-none w-full">
    <canvas width={720} height={480} class="w-full bg-slate-400 m-1" />
  </div>
  <div class="flex-none w-full">
    <canvas width={720} height={480} class="w-full bg-slate-400 m-1" />
  </div>
</a-track>

Attributes


Name Type Default value Description
align undefined undefined

Item alignment in the track. "start" (left/top) or "center"

current undefined undefined

The index of the current item.

loop undefined undefined

Whether the track should loop back to the start when reaching the end.

overflow undefined undefined

Change the overflow behavior.

  • "auto" - Only scrollable when necessary.
  • "scroll" - Always scrollable.
  • "ignore" - Ignore any overflow.
snap undefined undefined

Whether the track should snap to the closest child element.

vertical undefined undefined

Whether the track should scroll vertically, instead of horizontally.

Events


Name Description
format

Emitted when: slots changed, window load and resize or children size changes. Can be canceled.

change

Emitted when the current index changed.

scroll

Emitted when the position changed.

move

Emitted when the position is about to cahnge by a user action. Can be canceled.

Methods


Track.addTrait(trait: T)

src/Track.ts:901

Add a trait.

Track.elementItemIndex(ele: HTMLElement)

src/Track.ts:952

Get the index of the item that contains given element. Returns -1 if it is not in any item.

Track.findTrait(id: string)

src/Track.ts:911

Get a trait by id.

Track.getClosestItemPosition(offset: number)

src/Track.ts:930

Get the absolute position of the closest item to the current position.

Track.getItemAtPosition(pos: Vec2)

src/Track.ts:1359

Get the item at a specific position.

Track.getToItemPosition(index: number)

src/Track.ts:964

Get the position of the item to the given index, relative to the current item.

Track.moveBy(byItems: number, easing: Easing)

src/Track.ts:1025

Move by given count of items.

Track.moveTo(index: number, easing: Easing)

src/Track.ts:1039

Move to index of item.

Track.removeTrait(trait: Trait)

src/Track.ts:906

Remove a trait.

Track.setTarget(vec: undefined | Vec2 | number[], ease: Easing)

src/Track.ts:997

Set the target position to transition to.

Track.startAnimate()

src/Track.ts:1043

Track.stopAnimate()

src/Track.ts:1050

Trait

The Track implements a trait system, which can be used to add new behaviours to the track.

Custom traits can be added to the track by calling the Track.addTrait method.

Or the Track class can be extended to override add new behaviours entirely.

Example


import { type InputState, Track, type Trait } from "@sv/elements/track";

export class CustomTrack extends Track {
  public traits: Trait[] = [
    // satefies the "Trait" interface
    {
      id: "custom-trait",
      input(track: Track, inputState: InputState) {
        if (inputState.release.value) {
          // log track posiiton on pointer/touch release
          console.log(track.posiiton);
        }
      },
    },
  ];
}

customElements.define("custom-track", CustomTrack);

SnapTrait

The SnapTrait addes the snapping of items to the track.

Examples

Different example configurations of tracks.

Free scroll

Snap scroll

Align center

Arrow key navigation

Vertical snap scroll

Dynamic children

When children change, and the last selected item does not exist anymore, it will recover to the closest available child.

Configure format behaviour:

track.addEventListener("format", e => {
  // prevent default behaviour (move to the closest available child)
  e.preventDefault();
  // instead move to the first child
  e.currentTarget?.moveTo(0);
});

Nested

Loop Snap