Pattern sampler
Tables, code, and cards
Compare the same progressive enhancement across three kinds of semantic, horizontally overflowing content.
Dependency-free TypeScript plugin
A11y Scroll Cue adds a visible text hint and an overflow-only keyboard tab stop to wide tables, code samples, card strips, and other semantic content—without replacing native scrolling.
Quick facts
a11y-scroll-cueLive demos
Both pages use the compiled package from dist. Start
with the basic patterns, then test a resettable real-world workflow.
Pattern sampler
Compare the same progressive enhancement across three kinds of semantic, horizontally overflowing content.
SaaS control room
Review a wide release table, dismiss the cue by scrolling, and restore it with a status-aware reset control.
Installation
The package is ESM-only and does not initialize anything when it is imported.
npm install a11y-scroll-cue
Basic usage
The original content remains available without JavaScript. The generated cue sits beside—not inside—the scrollable content.
<div
data-a11y-scroll-cue
data-a11y-scroll-cue-region-label="Feature comparison"
>
<div data-a11y-scroll-cue-scrollport>
<table>...</table>
</div>
</div>
import { createA11yScrollCue } from "a11y-scroll-cue";
import "a11y-scroll-cue/styles.css";
const root = document.querySelector("[data-a11y-scroll-cue]");
if (root instanceof HTMLElement) {
createA11yScrollCue(root, {
regionLabel: "Feature comparison",
});
}
Options
JavaScript options override matching data attributes. Invalid booleans and negative or non-numeric thresholds fall back to the documented defaults.
| Option | Default | Purpose |
|---|---|---|
message |
"Scroll horizontally" |
Sets the visible cue text. |
threshold |
2 |
Sets the overflow tolerance in CSS pixels. |
hideOnScroll |
true |
Dismisses the cue after real horizontal scrolling. |
focusable |
true |
Adds a tab stop only while overflow exists. |
observeMutations |
true |
Rechecks overflow after relevant content changes. |
regionLabel |
Empty string | Names an overflowing focusable region when needed. |
describeScrollport |
false |
Links the visible cue through
aria-describedby.
|
API and lifecycle
createA11yScrollCue()Enhances one root and returns the same instance if called again for that element.
initA11yScrollCueAll()Enhances every matching root in a document or supplied subtree.
update() and reset()Reconcile overflow state or make an eligible cue visible again.
dismiss() and destroy()Hide the cue deliberately or fully restore plugin-added state.
Successful initialization is synchronous:
init → update → ready. The root also dispatches
error, overflow-change,
dismiss, reset, and
destroy events. They bubble but are not cancelable or
composed across Shadow DOM boundaries.
Accessibility behavior
focusable is enabled.
regionLabel names the focusable overflow
region unless the author already provided a name.
describeScrollport is an explicit opt-in.
| Key | Behavior |
|---|---|
| Tab | Reaches the scrollport only while it has horizontal overflow. |
| ArrowLeft / ArrowRight | Uses the browser’s native horizontal scrolling behavior. |
| Home, End, and page keys | Remain browser-controlled; the plugin does not intercept them. |
Styling hooks
Import the package stylesheet, then override public properties on
.a11y-scroll-cue. Default transitions respect
prefers-reduced-motion.
.a11y-scroll-cue {
--a11y-scroll-cue-background: Canvas;
--a11y-scroll-cue-color: CanvasText;
--a11y-scroll-cue-border-color: currentColor;
--a11y-scroll-cue-hint-background: Canvas;
--a11y-scroll-cue-hint-color: CanvasText;
--a11y-scroll-cue-shadow: 0.25rem 0.25rem 0 currentColor;
--a11y-scroll-cue-radius: 0;
--a11y-scroll-cue-z-index: 2;
}
Limitations