---
title: Stack
description: >-
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.
api_version: 2025-07
api_name: pos-ui-extensions
source_url:
html: >-
https://shopify.dev/docs/api/pos-ui-extensions/2025-07/ui-components/layout-and-structure/stack
md: >-
https://shopify.dev/docs/api/pos-ui-extensions/2025-07/ui-components/layout-and-structure/stack.md
---
# 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.
## Properties
Configure the following properties on the `Stack` component.
* alignContent
'stretch' | ContentPosition | ContentDistribution
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](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content).
* alignItems
'stretch' | 'baseline' | ContentPosition
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](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items).
* blockSize
SizeUnitsOrAuto
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](https://developer.mozilla.org/en-US/docs/Web/CSS/block-size).
* columnGap
SpacingKeyword | ''
Default: '' - meaning no override
The spacing between elements in the inline axis. Overrides the column value of gap.
* direction
'inline' | 'block' | DeprecatedStackDirection
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.
* flex
number
The flex value for the `Stack` component. A value of 1 will stretch the component to fill the parent container.
* flexChildren
boolean
A boolean that determines 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` component.
* inlineSize
SizeUnitsOrAuto
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](https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size).
* justifyContent
ContentPosition | ContentDistribution
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](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content).
* maxBlockSize
SizeUnitsOrNone
Default: 'none'
Adjusts the maximum block size (max-height in horizontal writing modes). Learn more about [max-block-size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/max-block-size).
* maxInlineSize
SizeUnitsOrNone
Default: 'none'
Adjusts the maximum inline size (max-width in horizontal writing modes). Learn more about [max-inline-size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/max-inline-size).
* minBlockSize
SizeUnits
Default: '0'
Adjusts the minimum block size (min-height in horizontal writing modes). Learn more about [min-block-size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/min-block-size).
* minInlineSize
SizeUnits
Default: '0'
Adjusts the minimum inline size (min-width in horizontal writing modes). Learn more about [min-inline-size on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/min-inline-size).
* padding
PaddingKeys
Default: '0'
Adjusts the padding on all edges of the box using predefined spacing values.
* paddingBlock
PaddingKeys
Default: '0'
Adjusts the padding on the block axis (vertical in horizontal writing modes). Overrides the block value from `padding`.
* paddingBlockEnd
PaddingKeys
Default: '0'
Adjusts the padding at the block-end edge (bottom in horizontal writing modes). Overrides the end value from `paddingBlock`.
* paddingBlockStart
PaddingKeys
Default: '0'
Adjusts the padding at the block-start edge (top in horizontal writing modes). Overrides the start value from `paddingBlock`.
* paddingInline
PaddingKeys
Default: '0'
Adjusts the padding on the inline axis (horizontal in horizontal writing modes). Overrides the inline value from `padding`.
* paddingInlineEnd
PaddingKeys
Default: '0'
Adjusts the padding at the inline-end edge (right in left-to-right languages). Overrides the end value from `paddingInline`.
* paddingInlineStart
PaddingKeys
Default: '0'
Adjusts the padding at the inline-start edge (left in left-to-right languages). Overrides the start value from `paddingInline`.
* rowGap
SpacingKeyword | ''
Default: '' - meaning no override
The spacing between elements in the block axis. 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
The wrap behavior for the children of the `Stack` component.
Deprecated
This property has no effect as content will always wrap.
* paddingHorizontal
HorizontalSpacing
deprecated
The horizontal padding around the `Stack` component.
Deprecated
Use the `paddingInline` prop instead.
* paddingVertical
VerticalSpacing
deprecated
The vertical padding around the `Stack` component.
Deprecated
Use the `paddingBlock` prop instead.
* spacing
Spacing
Default: 1
deprecated
The spacing between each child in the `Stack` component.
Deprecated
Use the `gap` prop instead.
### ContentPosition
Defines positioning values for aligning content within a container.
```ts
'center' | 'start' | 'end'
```
### ContentDistribution
Defines distribution strategies for spacing content within a container.
```ts
'space-around' | 'space-between' | 'space-evenly'
```
### SizeUnitsOrAuto
Extends SizeUnits to include \`'auto'\` for properties that can automatically size based on content.
```ts
SizeUnits | 'auto'
```
### SizeUnits
Defines CSS size units for dimensions, supporting pixel values, percentages, or zero.
```ts
`${number}px` | `${number}%` | `0`
```
### SpacingKeyword
Spacing values that can be used for gaps between elements, including all size keywords and \`'none'\` for no spacing.
```ts
SizeKeyword | 'none'
```
### SizeKeyword
Defines the standardized spacing scale used throughout the POS design system. Each keyword maps to a predetermined spacing value that ensures visual consistency across components. Values range from \`'0'\` (no spacing) through \`'2000'\` (maximum spacing), with increments designed to create harmonious visual rhythm and hierarchy.
```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
Extends SizeUnits to include \`'none'\` for properties that can be explicitly disabled.
```ts
SizeUnits | 'none'
```
### PaddingKeys
Defines the allowed padding values, including all standardized size keywords and \`'none'\` for no padding.
```ts
SizeKeyword | 'none'
```
### HorizontalSpacing
Deprecated horizontal spacing values using named size keywords.
```ts
'HalfPoint' | 'ExtraSmall' | 'Small' | 'Medium' | 'Large' | 'ExtraLarge' | 'ExtraExtraLarge'
```
### VerticalSpacing
Deprecated vertical spacing values using named size keywords.
```ts
'HalfPoint' | 'ExtraSmall' | 'Small' | 'Medium' | 'Large' | 'ExtraLarge'
```
### Spacing
Deprecated spacing values represented as numeric multipliers.
```ts
0.5 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 16
```
### Examples
* #### Layout elements horizontally or vertically
##### Description
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.
##### 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

## Best practices
* **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 the`justifyContent` 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.
## Limitations
Wrapping behavior is determined by direction—inline stacks wrap content while block stacks don't, which may not suit all layout requirements.
## Examples
Learn how to create flexible layouts with inline and block stacks, control alignment, and nest stacks for complex UIs.
### Examples
* #### Arrange elements vertically
##### Description
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.
##### 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();
});
```
* #### Center content on both axes
##### Description
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.
##### 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();
});
```
* #### Center elements horizontally
##### Description
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.
##### 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();
});
```
* #### Center elements vertically
##### Description
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.
##### 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();
});
```
* #### Create complex layouts with nested stacks
##### Description
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.
##### 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();
});
```
* #### Expand children to fill available space
##### Description
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.
##### 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();
});
```
* #### Space elements apart vertically
##### Description
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.
##### 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();
});
```
* #### Stretch elements to fill width
##### Description
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.
##### 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();
});
```
## Preview
