A Scroll Area keeps the browser’s own scrolling (wheel, touch, keyboard, focus and scroll anchoring) and replaces only the visible scrollbars. Constrain its height or width; its content decides how far it scrolls. A label names the viewport as a region, which helps when it holds a lot of content. Track clicks and drags preserve keyboard focus, temporarily suspend scroll snapping, and restore it on release, cancellation, disabling, removal or disconnection. Track wheel input leaves reached edges unconsumed for ancestor scrolling; control-wheel zoom is untouched.
Horizontal
orientation="horizontal" shows the horizontal track. The content needs an intrinsic width wider than the area, such as a row that does not wrap.
Horizontal
Default density
Compact density
Restart from the initial state
Show the copyable source
scrollbar-visibility decides when tracks appear. The default, automatic, shows each overflowing axis; on-hover and while-scrolling keep quiet surfaces clean, and always keeps the track visible as a cue that more content exists.
Visibility
Default density
Compact density
Restart from the initial state
Show the copyable source
The host exposes data-overflow-y-start and data-overflow-y-end while content is hidden past an edge. Use them for fades or shadows that tell people there is more to scroll. Scroll the viewport itself with the standard scrollTo and scrollTop APIs on viewportElement. No second scroll position or component change event is maintained. Horizontal offsets follow the native RTL model.
Edge fade
Default density
Compact density
Restart from the initial state
Show the copyable source
These terms govern your use of Tweakpad and any workspace you create or join.
You keep ownership of the content you upload. You grant us the rights needed to host and display it to the people you share it with.
Paid plans renew automatically each billing period until cancelled from the Billing page.
We may update these terms. Material changes are announced by email at least 30 days in advance.
Back to top
These terms govern your use of Tweakpad and any workspace you create or join.
You keep ownership of the content you upload. You grant us the rights needed to host and display it to the people you share it with.
Paid plans renew automatically each billing period until cancelled from the Billing page.
We may update these terms. Material changes are announced by email at least 30 days in advance.
Back to top
<style>
#scroll-area-fade[data-overflow-y-end] { mask-image: linear-gradient(to bottom, black 75%, transparent); }
#scroll-area-fade[data-overflow-y-start][data-overflow-y-end] { mask-image: linear-gradient(to bottom, transparent, black 25%, black 75%, transparent); }
#scroll-area-fade[data-overflow-y-start]:not([data-overflow-y-end]) { mask-image: linear-gradient(to bottom, transparent, black 25%); }
</style>
<div style="display:grid;gap:var(--tp-space-3);justify-items:start">
<tp-scroll-area id="scroll-area-fade" label="Terms of service" style="block-size:10rem;inline-size:18rem;max-inline-size:100%">
<div style="display:grid;gap:var(--tp-space-3);font-size:var(--tp-text-sm);line-height:var(--tp-leading-relaxed)">
<p style="margin:0">These terms govern your use of Tweakpad and any workspace you create or join.</p>
<p style="margin:0">You keep ownership of the content you upload. You grant us the rights needed to host and display it to the people you share it with.</p>
<p style="margin:0">Paid plans renew automatically each billing period until cancelled from the Billing page.</p>
<p style="margin:0">We may update these terms. Material changes are announced by email at least 30 days in advance.</p>
</div>
</tp-scroll-area>
<tp-button id="scroll-area-fade-top" variant="outline" size="sm">Back to top</tp-button>
</div>
<script type="module">
await customElements.whenDefined('tp-scroll-area');
const area = document.querySelector('#scroll-area-fade');
document.querySelector('#scroll-area-fade-top').addEventListener('click', () => {
area.viewportElement?.scrollTo({ top: 0, behavior: 'smooth' });
});
</script>
API Reference
Every element also accepts motion-policy.
Attributes
AttributePropertyTypeDefaultDescriptionaxisaxis'x' | 'y' | 'both' | undefined—Restricts scrolling to one axis, or shows both tracks for content that overflows both ways; takes precedence over orientation.labellabelstring''Names the viewport as a region, which helps when it holds a lot of content.scrollbar-visibilityscrollbarVisibilityScrollbarVisibility'automatic'When the tracks appear: on overflow, always, only while scrolling or only on hover.keep-mountedkeepMountedbooleanfalseKeeps a track rendered when its axis does not overflow; it stays hidden unless visibility is always.show-cornershowCornerbooleantrueRenders the corner where visible horizontal and vertical tracks meet.
Properties
PropertyTypeDefaultDescriptionscrollbarsreadonly ScrollbarOptions[] | undefined—Configures each track on its own (orientation, visibility, keep-mounted), replacing axis and orientation; an empty list keeps native scrolling with no custom tracks.overflowEdgeThresholdOverflowEdgeThreshold0How far, in pixels, content must be hidden past an edge before that edge counts as overflowing; one number or one per edge.viewportElementread-onlyHTMLElement | null—The native scrolling element, for scrollTo, scrollTop and scroll events; null before the first render.contentElementread-onlyHTMLElement | null—The element wrapping the slotted content inside the viewport; null before the first render.
Slots
SlotDescriptiondefaultThe scrolling content.
CSS parts
PartDescription::part(scroll-area)The root that positions the tracks over the viewport.::part(scroll-area-content)The wrapper of the slotted content inside the viewport.::part(scroll-area-corner)The square where a horizontal and a vertical track meet.::part(scroll-area-viewport)The native, focusable scrolling element.
Related
Components, widgets and patterns that use this one.