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