---
title: Stack
description: >-
A container for other components that allows them to be stacked horizontally
or vertically. When building complex UIs, this will be your primary building
block. Stacks always wrap the content to the next column or row.
api_version: 2025-07
api_name: pos-ui-extensions
source_url:
html: 'https://shopify.dev/docs/api/pos-ui-extensions/2025-07/components/stack'
md: 'https://shopify.dev/docs/api/pos-ui-extensions/2025-07/components/stack.md'
---
# Stackcomponent
A container for other components that allows them to be stacked horizontally or vertically. When building complex UIs, this will be your primary building block. Stacks always wrap the content to the next column or row.
## Stack
* alignContent
'stretch' | ContentPosition | ContentDistribution
Default: 'start'
Aligns the Stack along the cross axis.
* alignItems
'stretch' | 'baseline' | ContentPosition
Default: 'stretch'
Aligns the Stack's children along the cross axis.
* blockSize
SizeUnitsOrAuto
Default: 'auto'
Adjust the block size.
Auto takes the block size of the box's children.
* columnGap
SpacingKeyword | ''
Default: '' - meaning no override
Adjust spacing between elements in the inline axis.
This overrides the column value of `gap`.
* direction
'inline' | 'block' | DeprecatedStackDirection
Default: 'inline'
Sets how the Stack's children are placed within the Stack. 'vertical' and 'horizontal' are deprecated. Using these values will use the Stack implementation from 2024-10.
* flex
number
The flex value for the stack. Flex 1 will stretch the stack to fill the parent.
* flexChildren
boolean
Whether the children should be stretched to fill the cross axis.
* gap
SpacingKeyword
Default: '0'
The size of the gap between each child in the stack.
* inlineSize
SizeUnitsOrAuto
Default: 'auto'
Adjust the inline size.
Auto takes the inline size of the box's children.
* justifyContent
ContentPosition | ContentDistribution
Default: 'start'
Aligns the Stack along the main axis.
* maxBlockSize
SizeUnitsOrNone
Default: 'none'
Adjust the maximum block size.
* maxInlineSize
SizeUnitsOrNone
Default: 'none'
Adjust the maximum inline size.
* minBlockSize
SizeUnits
Default: '0'
Adjust the minimum block size.
* minInlineSize
SizeUnits
Default: '0'
Adjust the minimum inline size.
* padding
PaddingKeys
Default: '0'
Adjust the padding of all edges in pixels.
* paddingBlock
PaddingKeys
Default: '0'
Adjust the block-padding.
This overrides the block value of `padding`.
* paddingBlockEnd
PaddingKeys
Default: '0'
Adjust the block-end padding.
This overrides the block-end value of `paddingBlock`.
* paddingBlockStart
PaddingKeys
Default: '0'
Adjust the block-start padding.
This overrides the block-start value of `paddingBlock`.
* paddingInline
PaddingKeys
Default: '0'
Adjust the inline padding.
This overrides the inline value of `padding`.
* paddingInlineEnd
PaddingKeys
Default: '0'
Adjust the inline-end padding.
This overrides the inline-end value of `paddingInline`.
* paddingInlineStart
PaddingKeys
Default: '0'
Adjust the inline-start padding.
This overrides the inline-start value of `paddingInline`.
* rowGap
SpacingKeyword | ''
Default: '' - meaning no override
Adjust spacing between elements in the block axis.
This overrides the row value of `gap`.
* alignment
ContentPosition | ContentDistribution
Default: 'flex-start'
deprecated
The alignment of the children along the main axis.
Deprecated
Use the `justifyContent` prop instead.
* flexWrap
'wrap' | 'nowrap' | 'wrap-reverse'
deprecated
Wrap behavior for the children of the stack.
Deprecated
Has no effect, content will always wrap.
* paddingHorizontal
HorizontalSpacing
deprecated
The horizontal padding around the stack.
Deprecated
Use the `paddingInline` prop instead.
* paddingVertical
VerticalSpacing
deprecated
The vertical padding around the stack.
Deprecated
Use the `paddingBlock` prop instead.
* spacing
Spacing
Default: 1
deprecated
The spacing between each child in the stack.
Deprecated
Use the `gap` prop instead.
### ContentPosition
```ts
'center' | 'start' | 'end'
```
### ContentDistribution
```ts
'space-around' | 'space-between' | 'space-evenly'
```
### SizeUnitsOrAuto
```ts
SizeUnits | 'auto'
```
### SizeUnits
```ts
`${number}px` | `${number}%` | `0`
```
### SpacingKeyword
```ts
SizeKeyword | 'none'
```
### SizeKeyword
SizeKeyword maps to predetermined values in POS.
```ts
'0' | '025' | '050' | '100' | '200' | '250' | '300' | '350' | '400' | '450' | '500' | '600' | '700' | '800' | '900' | '1000' | '1100' | '1200' | '1400' | '1800' | '2000'
```
### DeprecatedStackDirection
```ts
'vertical' | 'horizontal'
```
### SizeUnitsOrNone
```ts
SizeUnits | 'none'
```
### PaddingKeys
```ts
SizeKeyword | 'none'
```
### HorizontalSpacing
```ts
'HalfPoint' | 'ExtraSmall' | 'Small' | 'Medium' | 'Large' | 'ExtraLarge' | 'ExtraExtraLarge'
```
### VerticalSpacing
```ts
'HalfPoint' | 'ExtraSmall' | 'Small' | 'Medium' | 'Large' | 'ExtraLarge'
```
### Spacing
```ts
0.5 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 16
```
### Examples
* #### Stack
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```
## Preview

## Examples
The following examples will demonstrate some, but not all of the abilities of the `Stack` component. For simplicity, these examples use the React version of the `Stack` component, but the same results will be achieved by using the same properties with the regular JS library.
## Inline Stack with default values
In this example, we specify `inline` for the `direction`. As you can see, we have two small buttons occupying just the amount of space that they need, at the left side of the `Stack`. This is because `justifyContent` is set to `start` by default. We also include a `gap` of "200".
### Examples
* #### Inline Stack with default values
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```

## Inline Stack with flexChildren
Similar to the example above, but this time we are specifying `flexChildren` to be `true`. This means that the two buttons will take up the max amount of space that they can within the `inline` stack.
### Examples
* #### Inline Stack with flexChildren
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```

## Inline Stack with centered children
You can also center elements in your `inline` stack. For this, you can specify the `justifyContent` to be `center`. However, in this case you also want `flexChildren` to be `false` (which is the default), so that the children can take up the minimal amount of space that they need, and be centered.
### Examples
* #### Inline Stack with centered children
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```

## Inline Stack with vertical axis centering
Here we have an `inline` stack with two children. The first is a block stack with two buttons, and the second is a single button. Since the first element has a greater intrinsic height, our main inline stack's intrinsic height is also increased. We can center both children component along the main axis (x-axis) by setting the `alignItems` property to `center`.
### Examples
* #### Inline Stack with vertical axis centering
##### React
```tsx
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', () => (
));
```
##### TS
```ts
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();
});
```

## Block Stack
You can specify your `Stack` to layout its children vertically by setting the `direction` property to `block`.
### Examples
* #### Block Stack
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```

## Block Stack with space between children
Here we are spacing out the children of our block stack by setting `justifyContent` to `space-between` in order to space the children out as much as possible along the vertical axis. Note that in this example, we removed the wrapping `ScrollView` in order to introduce a custom height by setting the `blockSize` to `50%`. We are also adding `inlinePadding` of `450` in order to mimic the padding applied to the UI Extension screen header.
### Examples
* #### Block Stack with space between children
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```

## Block Stack centered on both axes
You can center your block stack on the vertical axis by setting `justifyContent` to `center`. Next, you can set a custom size on your block stack by setting the `blockSize` and `inlineSize`. In this example we set them to `50%` and `100%` respectively. We can then center our elements along both axis of the stack by setting justifyContent to `center` to center the children vertically, and setting both `alignContent` and `alignItems` to `center`.
### Examples
* #### Block Stack centered on both axes
##### React
```tsx
import {
reactExtension,
Button,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
));
```
##### TS
```ts
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();
});
```

## Block Stack with horizontal stretching
This example demonstrates a block stack with elements stretched to fill the width of the container. By setting `alignContent` to `'stretch'`, the children will expand to fill the available horizontal space. This is useful when you want all elements to have consistent width, regardless of their content.
### Examples
* #### Block Stack with horizontally stretched contents
##### React
```tsx
import {
reactExtension,
SegmentedControl,
Stack,
Screen,
} from '@shopify/ui-extensions-react/point-of-sale';
import React from 'react';
export default reactExtension('pos.home.modal.render', () => (
console.log(`Selected segment with id: ${id}`)}
/>
));
```
##### TS
```ts
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();
});
```

## Nested Stack
Now that we've run through a few examples of what a stack can do, let's move on to something more complex. You can nest multiple stacks of different configurations to achieve a more complex UI. In this example, we will create a row that displays several labels and an icon. This will mimic some of the basic rows that you can find across different POS screens.
Let's put the `Selectable` aside for now; we'll get to that later. The first stack is which we can refer to as the parent stack, is set to inline. It has two main children, a block stack on the left, and an inline stack on the right. To space them out completely along the horizontal axis, we set our parent inline stack's `justifyContent` to `space-between`. We also specify the `inlineSize` to be `100%` to take up the full width of the screen.
The first child stack (the block stack) simply has a gap of 100 to space out the two `Text` components.
The second child stack (the inline stack) has a gap of 600 to space out the `Text` and the `Icon`. We also set the `alignItems` and `alignContent` properties to `center` to center the `Text` and `Icon` within their stack.
However, we also need to the `alignItems` and `alignContent` properties to `center` on the parent inline stack to center the two children stacks along the vertical axis.
Finally, we can return to the `Selectable`. You'll notice that we've wrapped the entire stack in a `Selectable`. This makes the entire stack within the `Selectable` become a tappable surface, with an `onPress` handler, which is part of the `Selectable` component. It also gives a nice highlight effect when you tap, as you can see in the screenshot.
### Examples
* #### Nested Stack
##### React
```tsx
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', () => (
console.log('Pressed')}>
Hello world!
This is an example of a nested stack!
Let's go!
));
```
##### TS
```ts
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();
});
```
