Skip to content

TranslatedScroll Component

The TranslatedScroll component creates a horizontally scrollable container with smooth CSS transform-based scrolling. It supports mouse wheel scrolling, touch/mouse dragging, and an optional custom scrollbar.

Features

  • Transform-based Scrolling: Uses CSS translateX for smooth, GPU-accelerated horizontal scrolling
  • Mouse Wheel Support: Scroll horizontally using mouse wheel or trackpad
  • Touch & Mouse Drag: Drag content horizontally on touch devices or with mouse
  • Custom Scrollbar: Optional draggable scrollbar with automatic visibility
  • Responsive: Automatically adapts to container size changes using ResizeObserver
  • Overflow Detection: Scrollbar only appears when content exceeds container width

Configuration

ts
export interface TranslatedScrollOptions {
    innerWrapperSelector?: string;   // Selector for the scrolling content wrapper
    showScrollbar?: boolean;          // Show custom scrollbar (default: true)
    enableMouseDrag?: boolean;        // Enable mouse drag on desktop (default: false)
}

Basic Usage

Minimal Setup

html
<div x-data="TranslatedScroll()">
    <div class="content">
        <!-- Wide content that needs horizontal scrolling -->
        <div class="item">Item 1</div>
        <div class="item">Item 2</div>
        <div class="item">Item 3</div>
        <!-- ... more items -->
    </div>
</div>

With Options

html
<div x-data="TranslatedScroll({
    innerWrapperSelector: '.scroll-content',
    showScrollbar: true,
    enableMouseDrag: true
})">
    <div class="scroll-content">
        <!-- Your scrollable content -->
    </div>
</div>

Statamic Template Example

The package includes a reference implementation in the form of a faded scroll container:

antlers
{{# resources/views/partials/_faded_translated_scroll.antlers.html #}}
<div class="faded-translated-scroll {{ class ?? '' }}"
     x-data="TranslatedScroll({innerWrapperSelector: '.faded-translated-scroll-content'})">
    <div class="faded-translated-scroll-background">
        <div class="faded-translated-scroll-content">
            {{ slot }}
        </div>
    </div>
</div>

Usage in Statamic templates:

antlers
{{ partial:partials/faded_translated_scroll class="my-scroll-container" }}
    <div class="items">
        {{ collection:items }}
            <div class="item">{{ title }}</div>
        {{ /collection:items }}
    </div>
{{ /partial:partials/faded_translated_scroll }}

How It Works

CSS Transform Scrolling

The component uses a CSS variable --scroll-x to control horizontal positioning via transform: translateX():

css
.a-translated-scroll-inner-wrapper {
    transform: translateX(var(--scroll-x));
}

This provides smooth, GPU-accelerated scrolling without relying on the browser's native overflow scrolling.

Inner Wrapper Selector

The component needs to know which element contains the scrollable content:

  • Default: Uses the first child element of the component root
  • Custom: Specify innerWrapperSelector to target a specific nested element
html
<!-- Default: first child is used -->
<div x-data="TranslatedScroll()">
    <div><!-- This will be the scrolling wrapper --></div>
</div>

<!-- Custom: specific selector -->
<div x-data="TranslatedScroll({innerWrapperSelector: '.content'})">
    <div class="background">
        <div class="content"><!-- This will be the scrolling wrapper --></div>
    </div>
</div>

Automatic Resize Handling

The component uses ResizeObserver to watch both the container and inner wrapper for size changes. When dimensions change, it recalculates the maximum scroll width and updates the scrollbar accordingly.

Interaction Methods

Mouse Wheel Scrolling

Horizontal scrolling is triggered by vertical mouse wheel movement. The component prevents the default vertical scroll behavior and translates it to horizontal movement.

Touch Dragging

On touch devices, users can drag the content horizontally. The component tracks touch events and updates the scroll position in real-time.

Mouse Dragging

When enableMouseDrag: true, desktop users can click and drag the content. The cursor changes to grab when hovering and grabbing while dragging.

Scrollbar Dragging

The custom scrollbar can be clicked and dragged to navigate through the content. The scrollbar width is proportional to the visible content area.

Styling

The component applies CSS classes automatically:

Container Classes

  • .a-translated-scroll - Applied to the root element
  • .is-draggable - Added when enableMouseDrag is enabled
  • .is-dragging - Added during active drag operation

Inner Wrapper Classes

  • .a-translated-scroll-inner-wrapper - Applied to the scrolling content wrapper

Scrollbar Classes

  • .a-translated-scroll-scrollbar - The custom scrollbar element
  • .is-draggable - Added when content overflows and scrollbar is usable
  • .is-dragging - Added during active scrollbar drag

Customizing Scrollbar

Override the default scrollbar styles:

css
.a-translated-scroll-scrollbar {
    height: 8px;
    background: rgba(0, 0, 0, 0.3);
    border-radius: 8px;
}

.a-translated-scroll-scrollbar:hover,
.a-translated-scroll-scrollbar.is-dragging {
    background: rgba(0, 0, 0, 0.5);
}

Example: Faded Edges

Create a container with faded edges to indicate scrollable content:

css
.faded-translated-scroll {
    position: relative;
    overflow: hidden;
}

.faded-translated-scroll-background {
    position: relative;

    &::before,
    &::after {
        content: '';
        position: absolute;
        top: 0;
        bottom: 0;
        width: 50px;
        pointer-events: none;
        z-index: 1;
    }

    &::before {
        left: 0;
        background: linear-gradient(to right, white, transparent);
    }

    &::after {
        right: 0;
        background: linear-gradient(to left, white, transparent);
    }
}

.faded-translated-scroll-content {
    display: flex;
    gap: 20px;
    padding: 20px 0;
}

Browser Compatibility

The component uses modern browser APIs:

  • ResizeObserver: Supported in all modern browsers
  • CSS Custom Properties: Supported in all modern browsers
  • Touch Events: Supported on touch devices
  • Transform: Hardware-accelerated in all modern browsers

Use Cases

  • Image Galleries: Horizontal scrolling image carousels
  • Product Lists: Scrollable product showcases
  • Timeline Components: Horizontal timeline navigation
  • Data Tables: Wide tables with horizontal scrolling
  • Card Layouts: Scrollable card decks
  • Tag Lists: Overflow tag collections

Performance

The component is optimized for performance:

  • GPU Acceleration: Uses CSS transforms for smooth scrolling
  • Debounced Updates: Resize calculations are debounced with setTimeout
  • Passive Event Listeners: Uses passive listeners where possible
  • Minimal DOM Updates: Only updates necessary CSS properties