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.

Stack

The Stack component organizes elements horizontally or vertically along the block or inline axis. Use it to structure layouts, group related components, or control spacing between elements with flexible alignment options.

The component simplifies layout creation by automatically managing spacing between child elements through gap properties, eliminating the need for manual margin management. It supports both horizontal and vertical arrangements, flexible alignment options, and wrapping behavior, making it the foundation for building consistent, responsive layouts throughout POS extensions.

Stack components support responsive gap values that automatically adjust spacing based on screen size, ensuring layouts remain visually balanced and maintain proper element separation across different devices.


Configure the following properties on the Stack component.

Anchor to alignContent
alignContent
'stretch' | |
Default: 'start'

The alignment of the Stack component along the cross axis, controlling how content is distributed when there's extra space. Learn more about align-content on MDN.

Anchor to alignItems
alignItems
'stretch' | 'baseline' |
Default: 'stretch'

The alignment of the Stack component's children along the cross axis, controlling how individual items are positioned. Learn more about align-items on MDN.

Anchor to blockSize
blockSize
Default: 'auto'

Adjusts the block size (height in horizontal writing modes). Use 'auto' to take the block size of the box's children. Learn more about block-size on MDN.

Anchor to columnGap
columnGap
| ''
Default: '' - meaning no override

The spacing between elements in the inline axis. Overrides the column value of gap.

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

The direction in which children are placed within the Stack component. Use 'block' for vertical arrangement along the block axis without wrapping, or 'inline' for horizontal arrangement along the inline axis with automatic wrapping.

number

The flex value for the Stack component. A value of 1 will stretch the component to fill the parent container.

Anchor to flexChildren
flexChildren
boolean

A boolean that determines whether the children should be stretched to fill the cross axis.

Default: '0'

The size of the gap between each child in the Stack component.

Anchor to inlineSize
inlineSize
Default: 'auto'

Adjusts the inline size (width in horizontal writing modes). Use 'auto' to take the inline size of the box's children. Learn more about inline-size on MDN.

Anchor to justifyContent
justifyContent
|
Default: 'start'

The alignment of the Stack component along the main axis, controlling how space is distributed between and around content items. Learn more about justify-content on MDN.

Anchor to maxBlockSize
maxBlockSize
Default: 'none'

Adjusts the maximum block size (max-height in horizontal writing modes). Learn more about max-block-size on MDN.

Anchor to maxInlineSize
maxInlineSize
Default: 'none'

Adjusts the maximum inline size (max-width in horizontal writing modes). Learn more about max-inline-size on MDN.

Anchor to minBlockSize
minBlockSize
Default: '0'

Adjusts the minimum block size (min-height in horizontal writing modes). Learn more about min-block-size on MDN.

Anchor to minInlineSize
minInlineSize
Default: '0'

Adjusts the minimum inline size (min-width in horizontal writing modes). Learn more about min-inline-size on MDN.

Anchor to padding
padding
Default: '0'

Adjusts the padding on all edges of the box using predefined spacing values.

Anchor to paddingBlock
paddingBlock
Default: '0'

Adjusts the padding on the block axis (vertical in horizontal writing modes). Overrides the block value from padding.

Anchor to paddingBlockEnd
paddingBlockEnd
Default: '0'

Adjusts the padding at the block-end edge (bottom in horizontal writing modes). Overrides the end value from paddingBlock.

Anchor to paddingBlockStart
paddingBlockStart
Default: '0'

Adjusts the padding at the block-start edge (top in horizontal writing modes). Overrides the start value from paddingBlock.

Anchor to paddingInline
paddingInline
Default: '0'

Adjusts the padding on the inline axis (horizontal in horizontal writing modes). Overrides the inline value from padding.

Anchor to paddingInlineEnd
paddingInlineEnd
Default: '0'

Adjusts the padding at the inline-end edge (right in left-to-right languages). Overrides the end value from paddingInline.

Anchor to paddingInlineStart
paddingInlineStart
Default: '0'

Adjusts the padding at the inline-start edge (left in left-to-right languages). Overrides the start value from paddingInline.

Anchor to rowGap
rowGap
| ''
Default: '' - meaning no override

The spacing between elements in the block axis. Overrides the row value of gap.

Anchor to alignment
alignment
|
Default: 'flex-start'

The alignment of the children along the main axis.

Deprecated

Use the justifyContent prop instead.

Anchor to flexWrap
flexWrap
'wrap' | 'nowrap' | 'wrap-reverse'

The wrap behavior for the children of the Stack component.

Deprecated

This property has no effect as content will always wrap.

Anchor to paddingHorizontal
paddingHorizontal

The horizontal padding around the Stack component.

Deprecated

Use the paddingInline prop instead.

Anchor to paddingVertical
paddingVertical

The vertical padding around the Stack component.

Deprecated

Use the paddingBlock prop instead.

Anchor to spacing
spacing
Default: 1

The spacing between each child in the Stack component.

Deprecated

Use the gap prop instead.


Anchor to Layout elements horizontally or verticallyLayout elements horizontally or vertically

Organize UI elements horizontally or vertically with automatic spacing management. This example shows a Stack with default values, demonstrating how to structure layouts and control element spacing through gap properties without manual margin management.

Layout elements horizontally or vertically

Organize UI elements horizontally or vertically with automatic spacing management. This example shows a Stack with default values, demonstrating how to structure layouts and control element spacing through gap properties without manual margin management.

Layout elements horizontally or vertically

import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack direction="inline" gap="200">
<Button title="Hello" />
<Button title="Hello" />
</Stack>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const stack = root.createComponent(Stack, {
direction: 'inline',
gap: '200',
});
stack.append(button1, button2);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

Anchor to Arrange elements verticallyArrange elements vertically

Stack elements vertically by setting direction="block". This creates a vertical layout with automatic gap spacing between elements, ideal for forms, lists, or any vertically-stacked content.

Arrange elements vertically

Stack elements vertically by setting `direction='block'`. This creates a vertical layout with automatic gap spacing between elements, ideal for forms, lists, or any vertically-stacked content.

Arrange elements vertically

import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack direction="block" gap="200" paddingInline="450">
<Button title="Hello" />
<Button title="Hello" />
<Button title="Hello" />
</Stack>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const button3 = root.createComponent(Button, {
title: 'Hello',
});

const stack = root.createComponent(Stack, {
direction: 'block',
gap: '200',
paddingInline: '450',
});
stack.append(button1, button2, button3);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

Anchor to Center content on both axesCenter content on both axes

Center elements both horizontally and vertically using justifyContent="center", alignContent="center", and alignItems="center" with custom blockSize="50%" and inlineSize="100%". All three alignment properties work together to create perfectly centered content on both axes.

Center content on both axes

Center elements both horizontally and vertically using `justifyContent='center'`, `alignContent='center'`, and `alignItems='center'` with custom `blockSize='50%'` and `inlineSize='100%'`. All three alignment properties work together to create perfectly centered content on both axes.

Center content on both axes

import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack
direction="block"
gap="200"
justifyContent="center"
alignContent="center"
alignItems="center"
inlineSize="100%"
paddingInline="450"
blockSize="50%"
>
<Button title="Hello" />
<Button title="Hello" />
</Stack>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const stack = root.createComponent(Stack, {
direction: 'block',
justifyContent: 'center',
alignContent: 'center',
alignItems: 'center',
inlineSize: '100%',
paddingInline: '450',
blockSize: '50%',
gap: '200',
});
stack.append(button1, button2);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

Anchor to Center elements horizontallyCenter elements horizontally

Center elements horizontally using justifyContent="center" with flexChildren={false} (default). This positions children in the center while keeping them at their minimum required size, ideal for centered button groups without stretching.

Center elements horizontally

Center elements horizontally using `justifyContent='center'` with `flexChildren={false}` (default). This positions children in the center while keeping them at their minimum required size, ideal for centered button groups without stretching.

Center elements horizontally

import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack direction="inline" gap="200" justifyContent="center">
<Button title="Hello" />
<Button title="Hello" />
</Stack>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const stack = root.createComponent(Stack, {
direction: 'inline',
gap: '200',
justifyContent: 'center',
});
stack.append(button1, button2);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

Anchor to Center elements verticallyCenter elements vertically

Center children along the vertical axis using alignItems="center". This example shows an inline stack with two children of different heights (a nested block stack and a button)—since the block stack has greater intrinsic height, alignItems="center" centers both children along the cross-axis.

Center elements vertically

Center children along the vertical axis using `alignItems='center'`. This example shows an inline stack with two children of different heights (a nested block stack and a button)—since the block stack has greater intrinsic height, `alignItems='center'` centers both children along the cross-axis.

Center elements vertically

import {
reactExtension,
Button,
Stack,
Screen,
ScrollView,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<ScrollView>
<Stack
direction="inline"
gap="200"
alignItems="center"
alignContent="center"
>
<Stack direction="block" gap="200">
<Button title="Hello" />
<Button title="Hello" />
</Stack>
<Button title="Hello" />
</Stack>
</ScrollView>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
ScrollView,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const button3 = root.createComponent(Button, {
title: 'Hello',
});

const innerStack = root.createComponent(Stack, {
direction: 'block',
gap: '200',
});
innerStack.append(button1, button2);

const mainStack = root.createComponent(Stack, {
direction: 'inline',
gap: '200',
alignItems: 'center',
alignContent: 'center',
});
mainStack.append(innerStack, button3);

const scrollView = root.createComponent(ScrollView);
scrollView.append(mainStack);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(scrollView);
root.append(screen);

root.mount();
});

Anchor to Create complex layouts with nested stacksCreate complex layouts with nested stacks

Nest multiple stacks to build sophisticated layouts. This example creates a tappable row using an inline parent stack with justifyContent="space-between" and inlineSize="100%" containing two child stacks: a block stack (left) with gap 100 for labels, and an inline stack (right) with gap 600 for text and icon. The entire structure is wrapped in a Selectable component for tap interaction with visual highlight.

Create complex layouts with nested stacks

Nest multiple stacks to build sophisticated layouts. This example creates a tappable row using an inline parent stack with `justifyContent='space-between'` and `inlineSize='100%'` containing two child stacks: a block stack (left) with gap 100 for labels, and an inline stack (right) with gap 600 for text and icon. The entire structure is wrapped in a Selectable component for tap interaction with visual highlight.

Create complex layouts with nested stacks

import {
reactExtension,
Text,
Icon,
Stack,
Screen,
Selectable,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Selectable onPress={() => console.log('Pressed')}>
<Stack
direction="inline"
gap="400"
justifyContent="space-between"
alignItems="center"
alignContent="center"
paddingInline="450"
paddingBlock="600"
inlineSize="100%"
>
<Stack direction="block" gap="100">
<Text>Hello world!</Text>
<Text variant="captionRegular">
This is an example of a nested stack!
</Text>
</Stack>
<Stack
direction="inline"
gap="600"
alignItems="center"
alignContent="center"
>
<Text>Let's go!</Text>
<Icon name="chevron-right" />
</Stack>
</Stack>
</Selectable>
</Screen>
));
import {
extension,
Text,
Icon,
Screen,
Stack,
Selectable,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const label1 = root.createComponent(Text);
label1.append('Hello world!');

const label2 = root.createComponent(Text, {variant: 'captionRegular'});
label2.append('This is an example of a nested stack!');

const price = root.createComponent(Text);
price.append("Let's go!");

const icon = root.createComponent(Icon, {
name: 'chevron-right',
});

const leftStack = root.createComponent(Stack, {
direction: 'block',
gap: '100',
});
leftStack.append(label1, label2);

const rightStack = root.createComponent(Stack, {
direction: 'inline',
gap: '600',
alignItems: 'center',
alignContent: 'center',
});
rightStack.append(price, icon);

const mainStack = root.createComponent(Stack, {
direction: 'inline',
gap: '400',
justifyContent: 'space-between',
alignItems: 'center',
alignContent: 'center',
paddingInline: '450',
paddingBlock: '600',
inlineSize: '100%',
});
mainStack.append(leftStack, rightStack);

const selectable = root.createComponent(Selectable, {
onPress: () => console.log('Pressed'),
});
selectable.append(mainStack);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(selectable);
root.append(screen);

root.mount();
});

Anchor to Expand children to fill available spaceExpand children to fill available space

Make child components expand to fill available space in an inline stack using flexChildren={true}. This stretches the two buttons to occupy maximum space within the inline container, distributing space evenly across children for full-width layouts.

Expand children to fill available space

Make child components expand to fill available space in an inline stack using `flexChildren={true}`. This stretches the two buttons to occupy maximum space within the inline container, distributing space evenly across children for full-width layouts.

Expand children to fill available space

import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack direction="inline" gap="200" flexChildren>
<Button title="Hello" />
<Button title="Hello" />
</Stack>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const stack = root.createComponent(Stack, {
direction: 'inline',
gap: '200',
flexChildren: true,
});
stack.append(button1, button2);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

Anchor to Space elements apart verticallySpace elements apart vertically

Distribute children vertically using justifyContent="space-between" with blockSize="50%" for custom height. This example removes the ScrollView wrapper and adds inlinePadding="450" to mimic screen header padding, spreading children across the available height with maximum spacing.

Space elements apart vertically

Distribute children vertically using `justifyContent='space-between'` with `blockSize='50%'` for custom height. This example removes the ScrollView wrapper and adds `inlinePadding='450'` to mimic screen header padding, spreading children across the available height with maximum spacing.

Space elements apart vertically

import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack
direction="block"
gap="200"
justifyContent="space-between"
blockSize="50%"
paddingInline="450"
>
<Button title="Hello" />
<Button title="Hello" />
<Button title="Hello" />
</Stack>
</Screen>
));
import {
extension,
Button,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const button1 = root.createComponent(Button, {
title: 'Hello',
});

const button2 = root.createComponent(Button, {
title: 'Hello',
});

const button3 = root.createComponent(Button, {
title: 'Hello',
});

const stack = root.createComponent(Stack, {
direction: 'block',
gap: '200',
justifyContent: 'space-between',
blockSize: '50%',
paddingInline: '450',
});
stack.append(button1, button2, button3);

const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

Anchor to Stretch elements to fill widthStretch elements to fill width

Stretch child elements to fill container width using alignContent="stretch". This makes all children expand horizontally to fill available space regardless of content, ensuring consistent full-width elements in vertical layouts.

Stretch elements to fill width

Stretch child elements to fill container width using `alignContent='stretch'`. This makes all children expand horizontally to fill available space regardless of content, ensuring consistent full-width elements in vertical layouts.

Stretch elements to fill width

import {
reactExtension,
SegmentedControl,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';

export default reactExtension('pos.home.modal.render', () => (
<Screen name="Stack" title="Stack">
<Stack direction="block" gap="400" alignContent="stretch" padding="400">
<SegmentedControl
selected="1"
segments={[
{id: '1', label: 'Segment 1', disabled: false},
{id: '2', label: 'Segment 2', disabled: false},
{id: '3', label: 'Segment 3', disabled: false},
{id: '4', label: 'Segment 4', disabled: false},
{id: '5', label: 'Segment 5', disabled: false},
{id: '6', label: 'Segment 6', disabled: false},
{id: '7', label: 'Segment 7', disabled: false},
]}
onSelect={(id) => console.log(`Selected segment with id: ${id}`)}
/>
</Stack>
</Screen>
));
import {
extension,
SegmentedControl,
Screen,
Stack,
} from '@shopify/ui-extensions/point-of-sale';

export default extension('pos.home.modal.render', (root) => {
const segmentedControl = root.createComponent(SegmentedControl, {
segments: [
{id: '1', label: 'Segment 1', disabled: false},
{id: '2', label: 'Segment 2', disabled: false},
{id: '3', label: 'Segment 3', disabled: false},
{id: '4', label: 'Segment 4', disabled: false},
{id: '5', label: 'Segment 5', disabled: false},
{id: '6', label: 'Segment 6', disabled: false},
{id: '7', label: 'Segment 7', disabled: false},
],
selected: '1',
onSelect: (id: string) => {
console.log(`Selected segment with id: ${id}`);
},
});
const stack = root.createComponent(Stack);
stack.append(segmentedControl);
const screen = root.createComponent(Screen, {
name: 'Stack',
title: 'Stack',
});
screen.append(stack);
root.append(screen);

root.mount();
});

  • Apply consistent spacing using the numeric scale: Use the predefined numeric spacing values (for example, '100', '300', '500') to maintain consistency across your interface. Start with '300' for standard spacing and adjust up or down based on your content hierarchy needs.
  • Use alignment properties for professional layouts: Use thejustifyContent property to control main axis distribution. Use alignItems for cross axis positioning of individual items, and alignContent for cross axis distribution when there's extra space.
  • Use gap properties for precise spacing control: Take advantage of the flexible gap system - use gap for uniform spacing, rowGap for block axis control, and columnGap for inline axis control.
  • Combine with other layout components strategically: Use the Stack component in combination with Box and Section components. Stack handles element arrangement and spacing, while other components provide additional layout capabilities.

Wrapping behavior is determined by direction—inline stacks wrap content while block stacks don't, which may not suit all layout requirements.


Was this page helpful?