Skip to main content
Migrate to Polaris

Version 2025-07 is the last API version to support React-based UI components. Later versions use web components, native UI elements with built-in accessibility, better performance, and consistent styling with Shopify's design system. Check out the migration guide to upgrade your extension.

ScrollView

The ScrollView component provides a scrollable container for long-form content that exceeds the available space. Use ScrollView to display lists, order summaries, or other lengthy content while maintaining a constrained layout.

ScrollView supports scroll event callbacks, direction control, and maximum size constraints to create bounded scrollable regions. For static layouts where all content should be visible, use BlockStack or View.

Support
Targets (25)

Configure the following properties on the ScrollView component.

Anchor to accessibilityLabel
accessibilityLabel
string

A label announced by assistive technologies that describes the purpose or contents of the element. Only set this when the element's visible content doesn't provide enough context on its own.

Anchor to background
background
<>
Default: 'transparent'

The background color of the element, set using a design-system keyword.

Anchor to border
border
<<>>

The border style of the element. Accepts a single value for all four edges, or a shorthand tuple for per-edge control:

  • 'base': Applies base to all edges.
  • ['base', 'none']: Block edges get base, inline edges get none.
  • ['base', 'none', 'dotted', 'base']: Values apply to block-start, inline-end, block-end, and inline-start respectively.
Anchor to borderWidth
borderWidth
< <> >

The border width of the element. Accepts a single value for all four edges, or a shorthand tuple for per-edge control:

  • 'base': Applies base to all edges.
  • ['base', 'medium']: Block edges get base, inline edges get medium.
  • ['base', 'medium', 'medium', 'base']: Values apply to block-start, inline-end, block-end, and inline-start respectively.
Anchor to cornerRadius
cornerRadius
< <> >

The corner radius of the element. Accepts a single value for all four corners, or a shorthand tuple for per-corner control using logical (writing-mode-aware) corners:

  • 'base': All four corners get base radius.
  • ['base', 'none']: StartStart/EndEnd get base, StartEnd/EndStart get none. In left-to-right mode, StartStart and EndEnd are the top-left and bottom-right corners.
  • ['base', 'none', 'small', 'base']: Values apply to StartStart, StartEnd, EndEnd, and EndStart respectively.

A borderRadius alias is available. When both are set, cornerRadius takes precedence.

Anchor to direction
direction
'block' | 'inline'
Default: block

The axis along which the content is scrollable.

  • block: Content scrolls along the main (block) axis.
  • inline: Content scrolls along the cross (inline) axis.
Anchor to display
display
<'auto' | 'none'>
Default: 'auto'

The display mode of the component. Learn more about display.

  • auto: The initial value; the actual behavior depends on the component and context.
  • none: Hides the component and removes it from the accessibility tree.
'innerShadow' | {type: 'pill'; content: string}

A visual hint indicating that the area is scrollable.

  • innerShadow: An inner shadow indicating that content continues beyond the visible area.
  • {type: 'pill', content: string}: A pill-shaped message displayed at the end of the scrollable area that disappears when the user starts scrolling.
string

A unique identifier for the component. Use this to target the component in scripts or stylesheets, or to distinguish it from other instances of the same component.

Anchor to maxBlockSize
maxBlockSize
< number | `${number}%` | 'fill' >

The maximum block size (maximum height in horizontal writing modes). The element won't grow taller than this value even if its content is longer.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's block size.
  • 'fill': Takes all the available space.

Learn more about the max-block-size property.

Anchor to maxInlineSize
maxInlineSize
< number | `${number}%` | 'fill' >

The maximum inline size (maximum width in horizontal writing modes). The element won't grow wider than this value.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's inline size.
  • 'fill': Takes all the available space.

Learn more about the max-inline-size property.

Anchor to minBlockSize
minBlockSize
< number | `${number}%` | 'fill' >

The minimum block size (minimum height in horizontal writing modes). The element won't shrink smaller than this value even if its content is shorter.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's block size.
  • 'fill': Takes all the available space.

Learn more about the min-block-size property.

Anchor to minInlineSize
minInlineSize
< number | `${number}%` | 'fill' >

The minimum inline size (minimum width in horizontal writing modes). The element won't shrink narrower than this value.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's inline size.
  • 'fill': Takes all the available space.

Learn more about the min-inline-size property.

Anchor to onScroll
onScroll
(args: ) => void

A callback fired when the scroll position changes. On touch devices, this fires only when the user finishes scrolling, unlike non-touch devices where it fires continuously during scrolling.

Anchor to onScrolledToEdge
onScrolledToEdge
(args: ) => void

A callback fired when the scroll position reaches one of the container's edges.

Anchor to padding
padding
<<>>

The padding on all edges of the element, using a shorthand syntax. You can specify one, two, or four values following the CSS shorthand convention.

  • T: A single value applied uniformly to all edges.
  • [T, T]: The first value applies to block-start and block-end, the second to inline-start and inline-end.
  • [T, T, T, T]: Values apply to block-start, inline-end, block-end, and inline-start respectively.
Anchor to scrollTo
scrollTo
number | HTMLElement

The initial scroll target when the component first renders. Accepts a pixel offset (number) to scroll to a specific position, or an HTMLElement to scroll that element into view. This only takes effect on the first render; subsequent updates to this prop are ignored.

Anchor to borderRadius
borderRadius
< <> >

The corner radius of the element. Accepts a single value for all four corners, or a shorthand tuple for per-corner control:

  • 'base': All four corners get base radius.
  • ['base', 'none']: StartStart/EndEnd get base, StartEnd/EndStart get none.
  • ['base', 'none', 'small', 'base']: Values apply to StartStart, StartEnd, EndEnd, and EndStart respectively.
Deprecated

Use cornerRadius instead.


Anchor to Display scrollable contentDisplay scrollable content

Use ScrollView to contain long content in a scrollable area. Set maxBlockSize to constrain the container height and enable vertical scrolling.

Display scrollable content

A ScrollView containing long-form content in a scrollable area.

Display scrollable content

import {
reactExtension,
ScrollView,
View,
} from '@shopify/ui-extensions-react/customer-account';

export default reactExtension(
'customer-account.page.render',
() => <Extension />,
);

function Extension() {
return (
<ScrollView maxBlockSize={300}>
<View
border="base"
padding="base"
minBlockSize={50}
>
View
</View>
<View
border="base"
padding="base"
minBlockSize={50}
>
View
</View>
<View
border="base"
padding="base"
minBlockSize={50}
>
View
</View>
<View
border="base"
padding="base"
minBlockSize={50}
>
View
</View>
<View
border="base"
padding="base"
minBlockSize={50}
>
View
</View>
</ScrollView>
);
}
import {extension, ScrollView, View} from '@shopify/ui-extensions/customer-account';

export default extension('customer-account.page.render', (root) => {
const scrollView = root.createComponent(ScrollView, {maxBlockSize: 400}, [
root.createComponent(
View,
{border: 'base', padding: 'base', minBlockSize: 50},
'View',
),
root.createComponent(
View,
{border: 'base', padding: 'base', minBlockSize: 50},
'View',
),
root.createComponent(
View,
{border: 'base', padding: 'base', minBlockSize: 50},
'View',
),
root.createComponent(
View,
{border: 'base', padding: 'base', minBlockSize: 50},
'View',
),
root.createComponent(
View,
{border: 'base', padding: 'base', minBlockSize: 50},
'View',
),
root.createComponent(
View,
{border: 'base', padding: 'base', minBlockSize: 50},
'View',
),
]);

root.appendChild(scrollView);
});

  • Set a reasonable max height: Choose a maxBlockSize that shows enough content for context. Showing 2-3 visible items before scrolling gives customers a clear indication that more content is available.
  • Provide an accessibility label: Set accessibilityLabel to describe the scrollable region so screen reader users understand what content is scrollable.
  • Don't nest scroll views: Avoid placing ScrollViews inside other ScrollViews. Nested scrollable regions create confusing navigation for keyboard and assistive technology users.
  • Use scroll callbacks for dynamic behavior: Use onScroll and onScrolledToEdge to trigger actions like loading more content when the customer reaches the bottom.

  • ScrollView doesn't support pull-to-refresh behavior. Infinite scrolling must be implemented manually using the onScrolledToEdge callback.
  • The scroll indicator styling is determined by the platform and can't be customized.
  • ScrollView requires a constrained height (via maxBlockSize or a parent with a fixed height) to enable scrolling. Without constraints, it expands to fit all content.

Was this page helpful?