Skip to main content

Stack

Available from version 0.6.0

Stack is a container component for arranging elements vertically or horizontally.

Basics

import { Stack } from 'tailwind-joy/components';

The Stack component acts as a generic container, wrapping around the elements to be arranged.

Use the spacing prop to control the space between children. The spacing value can be any number, including decimals, or a string.

Item 1
Item 2
Item 3
import type { ReactNode } from 'react';
import { Box, Sheet, Stack } from 'tailwind-joy/components';

function Item({ children }: { children?: ReactNode }) {
return (
<Sheet
className="
text-joy-neutral-700 border-joy-neutral-500/20 dark:border-joy-neutral-500/[.16]
dark:text-joy-neutral-300 rounded-[8px] border border-solid p-2 text-center
text-[length:var(--joy-fontSize-sm,0.875rem)] font-medium leading-[var(--joy-lineHeight-md,1.5)]
"
>
{children}
</Sheet>
);
}

export function StackBasics() {
return (
<Box className="w-full">
<Stack spacing="16px">
<Item>Item 1</Item>
<Item>Item 2</Item>
<Item>Item 3</Item>
</Stack>
</Box>
);
}

Customization

Direction

By default, Stack arranges items vertically in a column. Use the direction prop to position items horizontally in a row:

Item 1
Item 2
Item 3
import type { ReactNode } from 'react';
import { Sheet, Stack } from 'tailwind-joy/components';

function Item({ children }: { children?: ReactNode }) {
return (
<Sheet
className="
text-joy-neutral-700 border-joy-neutral-500/20 dark:border-joy-neutral-500/[.16]
dark:text-joy-neutral-300 rounded-[8px] border border-solid p-2 text-center
text-[length:var(--joy-fontSize-sm,0.875rem)] font-medium leading-[var(--joy-lineHeight-md,1.5)]
"
>
{children}
</Sheet>
);
}

export function StackDirection() {
return (
<div>
<Stack direction="row" spacing="8px">
<Item>Item 1</Item>
<Item>Item 2</Item>
<Item>Item 3</Item>
</Stack>
</div>
);
}

Dividers

Use the divider prop to insert an element between each child. This works particularly well with the Divider component, as shown below:

Item 1

Item 2

Item 3
import type { ReactNode } from 'react';
import { Box, Divider, Sheet, Stack } from 'tailwind-joy/components';

function Item({ children }: { children?: ReactNode }) {
return (
<Sheet
className="
text-joy-neutral-700 border-joy-neutral-500/20 dark:border-joy-neutral-500/[.16]
dark:text-joy-neutral-300 rounded-[8px] border border-solid p-2 text-center
text-[length:var(--joy-fontSize-sm,0.875rem)] font-medium leading-[var(--joy-lineHeight-md,1.5)]
"
>
{children}
</Sheet>
);
}

export function StackDividers() {
return (
<Box className="w-full">
<Stack
direction="row"
divider={<Divider orientation="vertical" />}
spacing="16px"
className="justify-center"
>
<Item>Item 1</Item>
<Item>Item 2</Item>
<Item>Item 3</Item>
</Stack>
</Box>
);
}

Flexbox gap

To use flexbox gap for the spacing implementation, set the useFlexGap prop to true. It removes the known limitations of the default implementation that uses a CSS nested selector.

Item 1
Item 2
Long content
import type { ReactNode } from 'react';
import { Box, Sheet, Stack } from 'tailwind-joy/components';

function Item({ children }: { children?: ReactNode }) {
return (
<Sheet
className="
text-joy-neutral-700 border-joy-neutral-500/20 dark:border-joy-neutral-500/[.16]
dark:text-joy-neutral-300 grow rounded-[8px] border border-solid p-2 text-center
text-[length:var(--joy-fontSize-sm,0.875rem)] font-medium leading-[var(--joy-lineHeight-md,1.5)]
"
>
{children}
</Sheet>
);
}

export function StackFlexboxGap() {
return (
<Box className="w-[200px]">
<Stack direction="row" spacing="8px" useFlexGap className="flex-wrap">
<Item>Item 1</Item>
<Item>Item 2</Item>
<Item>Long content</Item>
</Stack>
</Box>
);
}

Limitations

Margin on the children

Customizing the margin on the children is not supported by default.

For instance, the top-margin on the Button component below will be ignored.

<Stack>
<Button className="mt-[30px]">...</Button>
</Stack>
tip

To overcome this limitation, set useFlexGap prop to true to switch to CSS flexbox gap implementation.

white-space: nowrap

The initial setting on flex items is min-width: auto. This causes a positioning conflict when children use white-space: nowrap.

In order for the item to stay within the container you need to set min-width: 0.

<Stack direction="row" className="min-w-0">
<Typography noWrap>

Anatomy

The Stack component is composed of a single root <div> element:

<div class="tj-stack-root ...">
<!-- Stack contents -->
</div>

API

See the documentation below for a complete reference to all of the props available to the components mentioned here.