Alternating Rows
Several stacked rows of words gliding in opposite directions, every other one to the right, with a single Pause button for the whole block.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Gallery has 44 effects, including 6 free. Explore the category →
3 usage examples



How it works
Each .almq-row is a complete band: its window, its track and its list, written once. By default odd rows head left and even rows right, at 50 px per second; data-direction="left" or "right" on a row forces its direction, and data-speed on a row gives it its own speed (one slow row, one fast: that used to be a separate catalogue effect, here it is a plain attribute).
The script handles rows one by one: it measures each row's list, adds its duplicates, then sets its duration so the speed in pixels per second holds. Two rows of different lengths therefore move at the same pace and neither leaves a gap, even 1,900 px wide, where the old version broke apart beyond 600 px.
The .almq-rows block reacts as one: the mouse resting anywhere on it stops every row, and so does the Pause button. Colours come from --almq-color-1 to --almq-color-3 and repeat every three rows.
Accessibility
- Single Pause button: one
<button>witharia-pressedfor all rows, reachable with Tab; hovering the block also stops everything (WCAG 2.2.2). - One reading per row: each row is a list read once; its duplicates carry
aria-hidden="true". Before the repair, the three rows were each read twice. - Row direction: direction is decorative and not announced; if it carries meaning (outbound and return, for instance), also write it as text next to the rows.
- Reduced motion: under
prefers-reduced-motion: reduce, every row stands still, without duplicates or button, and each one can be scrolled by hand; a row that overflows also takes keyboard focus (Tab) and scrolls with the arrow keys. - Links: a row link receiving keyboard focus holds the whole block still, brings the rows back to their start and slides its own row to it.
Browser compatibility
One CSS animation per row, direction flipped with animation-direction, 4.5 KB of commented JavaScript, no dependency. ResizeObserver: Chrome 64, Firefox 69, Safari 13.1. Measured in Chromium 151, Firefox 153 and WebKit 26.5: three full rows at 390, 800 and 1,900 px, hover and button stop all three, two independent blocks, 0 errors.
Without JavaScript, rows stay still, each scrollable by hand. Without ResizeObserver, duplicates are only recounted when the window is resized.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0194-root" data-speed="50">
<div class="almq-band">
<div class="almq-rows">
<div class="almq-row">
<div class="almq-viewport">
<div class="almq-track">
<ul class="almq-group" role="list">
<li>First word</li>
<li>Second word</li>
</ul>
</div>
</div>
</div>
<div class="almq-row">
<div class="almq-viewport">
<div class="almq-track">
<ul class="almq-group" role="list">
<li>Another row</li>
<li>Other way</li>
</ul>
</div>
</div>
</div>
</div>
<button type="button" class="almq-toggle" aria-pressed="false" aria-label="Pause"></button>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Rows (HTML — the .almq-row elements) |
3 rows | As many rows as you like; each has its own list, written once. |
data-speed (root or row) |
50 | Pixels per second; on a row, it overrides the root's. |
data-direction (on a row) |
alternating | left or right forces the row's direction. |
--almq-color-1, -2, -3 |
#6366f1, #d946ef, #22d3ee | Colour of each row, repeating every three rows. |
--almq-size / --almq-space |
1.25rem / 4rem | Text size and gap between two items of a row. |
--almq-height / --almq-bg / --almq-padding |
180px / #0a0a0f / 1rem 0 | Demo frame; auto, transparent, 0 to set it inside a card. |
--almq-button / --almq-button-size |
rgba(255, 255, 255, .8) / 2rem | Colour and size of the button that stops the whole block. |
FAQ
.fx-0194-root roots holding one row each.data-speed to the row: <div class="almq-row" data-speed="120"> runs at 120 px/s while the others keep the root's speed.