VaneUI

VaneUI

Layout Components

Stack

A flexible layout component that arranges its children with consistent spacing. It can be used for both vertical and horizontal layouts.

SourceEdit this page

A vertical flex container with built-in padding and flexWrap. Think of Stack as Col plus padding and wrap — reach for it when you want a self-contained surface that breathes, not a structural skeleton.

Basic Stack

Stack defaults to column, flex, gap, padding, flexWrap, md, noBorder, noRing, outline, and sharp — you don't need to pass any of these. Pass href to render Stack as <a> instead of <div> — a focus-visible outline auto-enables when href is set.

Item 1
Item 2
Item 3
react-icon
<Stack>
<div className="p-4 bg-gray-100 rounded">Item 1</div>
<div className="p-4 bg-gray-100 rounded">Item 2</div>
<div className="p-4 bg-gray-100 rounded">Item 3</div>
</Stack>

Stack vs Col

Stack and Col are both vertical flex columns. The difference is opinion:

  • Stack = padding: true + flexWrap: true — a padded, wrap-friendly container.
  • Col = noPadding — a bare structural column you compose inside other surfaces.

Use Stack when the column owns its own breathing room. Use Col when an outer Card / Section / Container already supplies the padding.

Stack (padded by default)

Item 1
Item 2

Col (no padding)

Item 1
Item 2
react-icon
<Row itemsStart>
<Col flex1>
<Text semibold>Stack (padded by default)</Text>
<Stack className="border-2 border-dashed border-gray-300">
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
</Col>
<Col flex1>
<Text semibold>Col (no padding)</Text>
<Col className="border-2 border-dashed border-gray-300">
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Col>
</Col>
</Row>

Stack Direction

Use row for horizontal layout. Default is column (vertical).

column (default)

Item 1
Item 2

row

Item 1
Item 2
react-icon
<Row itemsStart>
<Col flex1>
<Text semibold>column (default)</Text>
<Stack className="border-2 border-dashed border-gray-300">
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
</Col>
<Col flex1>
<Text semibold>row</Text>
<Stack row className="border-2 border-dashed border-gray-300">
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
</Col>
</Row>

Stack Spacing

Use size props (xs, sm, md, lg, xl) to scale gap and padding together, or noGap to remove the gap.

xs

Item 1
Item 2

sm

Item 1
Item 2

md (default)

Item 1
Item 2

lg

Item 1
Item 2

xl

Item 1
Item 2
react-icon
<Row itemsStart>
<Stack xs flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>xs</Text>
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
<Stack sm flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>sm</Text>
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
<Stack flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>md (default)</Text>
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
<Stack lg flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>lg</Text>
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
<Stack xl flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>xl</Text>
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
</Stack>
</Row>

Padding Sizes

padding is on by default. The padding value scales with the size prop. Use noPadding to remove it entirely.

xs padding

Item

md padding (default)

Item

xl padding

Item

noPadding

Item
react-icon
<Row itemsStart>
<Stack xs filled secondary flex1>
<Text semibold>xs padding</Text>
<div className="p-2 bg-white/80 rounded">Item</div>
</Stack>
<Stack filled secondary flex1>
<Text semibold>md padding (default)</Text>
<div className="p-2 bg-white/80 rounded">Item</div>
</Stack>
<Stack xl filled secondary flex1>
<Text semibold>xl padding</Text>
<div className="p-2 bg-white/80 rounded">Item</div>
</Stack>
<Stack noPadding filled secondary flex1>
<Text semibold>noPadding</Text>
<div className="p-2 bg-white/80 rounded">Item</div>
</Stack>
</Row>

Items (Cross Axis)

Stack has no items default, so children stretch to fill the width. Override with itemsStart, itemsCenter, itemsEnd, itemsBaseline, or itemsStretch.

default (stretch)

A
B

itemsStart

A
B

itemsCenter

A
B

itemsEnd

A
B
react-icon
<Row itemsStart>
<Stack flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>default (stretch)</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack itemsStart flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>itemsStart</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack itemsCenter flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>itemsCenter</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack itemsEnd flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>itemsEnd</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
</Row>

Justify (Main Axis)

Control vertical distribution with justifyStart, justifyEnd, justifyCenter, justifyBetween, justifyAround, or justifyEvenly. The Stack needs a fixed height for these to have any effect.

justifyStart

A
B

justifyCenter

A
B

justifyEnd

A
B

justifyBetween

A
B

justifyAround

A
B

justifyEvenly

A
B
react-icon
<Row itemsStart>
<Stack justifyStart flex1 className="h-48 border-2 border-dashed border-gray-300">
<Text semibold>justifyStart</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack justifyCenter flex1 className="h-48 border-2 border-dashed border-gray-300">
<Text semibold>justifyCenter</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack justifyEnd flex1 className="h-48 border-2 border-dashed border-gray-300">
<Text semibold>justifyEnd</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack justifyBetween flex1 className="h-48 border-2 border-dashed border-gray-300">
<Text semibold>justifyBetween</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack justifyAround flex1 className="h-48 border-2 border-dashed border-gray-300">
<Text semibold>justifyAround</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
<Stack justifyEvenly flex1 className="h-48 border-2 border-dashed border-gray-300">
<Text semibold>justifyEvenly</Text>
<div className="p-2 bg-gray-100 rounded">A</div>
<div className="p-2 bg-gray-100 rounded">B</div>
</Stack>
</Row>

Wrap Behavior

flexWrap is on by default. In a horizontal Stack, items wrap to the next line when they would overflow the container. Use flexNoWrap to force everything onto a single line.

flexWrap (default) — items wrap when they overflow

Item 1
Item 2
Item 3
Item 4
Item 5

flexNoWrap — items shrink to fit

Item 1
Item 2
Item 3
Item 4
Item 5
react-icon
<Col>
<Text semibold>flexWrap (default) — items wrap when they overflow</Text>
<Stack row className="max-w-md border-2 border-dashed border-gray-300">
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
<div className="p-3 bg-gray-100 rounded">Item 3</div>
<div className="p-3 bg-gray-100 rounded">Item 4</div>
<div className="p-3 bg-gray-100 rounded">Item 5</div>
</Stack>
<Text semibold>flexNoWrap — items shrink to fit</Text>
<Stack row flexNoWrap className="max-w-md border-2 border-dashed border-gray-300">
<div className="p-3 bg-gray-100 rounded">Item 1</div>
<div className="p-3 bg-gray-100 rounded">Item 2</div>
<div className="p-3 bg-gray-100 rounded">Item 3</div>
<div className="p-3 bg-gray-100 rounded">Item 4</div>
<div className="p-3 bg-gray-100 rounded">Item 5</div>
</Stack>
</Col>

Stack Variants

Use filled or outline with appearance props for styled containers. Stack defaults to sharp — pair with rounded or pill for curved corners.

Filled Primary
Item 2
Outline Success
Item 2
react-icon
<Row itemsStart>
<Stack filled primary rounded flex1>
<div className="p-4 bg-white/80 rounded">Filled Primary</div>
<div className="p-4 bg-white/80 rounded">Item 2</div>
</Stack>
<Stack border success rounded flex1>
<div className="p-4 rounded">Outline Success</div>
<div className="p-4 rounded">Item 2</div>
</Stack>
</Row>

Text Alignment

Use textLeft, textCenter, textRight, or textJustify to control text alignment within the stack.

Left Aligned

Content aligned to the left.

Center Aligned

Content centered within the stack.

Right Aligned

Content aligned to the right.

react-icon
<Row itemsStart>
<Stack textLeft flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>Left Aligned</Text>
<Text>Content aligned to the left.</Text>
</Stack>
<Stack textCenter flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>Center Aligned</Text>
<Text>Content centered within the stack.</Text>
</Stack>
<Stack textRight flex1 className="border-2 border-dashed border-gray-300">
<Text semibold>Right Aligned</Text>
<Text>Content aligned to the right.</Text>
</Stack>
</Row>

Responsive Layout

Use mobileCol or tabletCol on a horizontal Stack to switch back to a column on narrower viewports.

Column 1

Horizontal on desktop, stacked on tablet and below.

Column 2

Resize to see the responsive behavior.

react-icon
<Stack row tabletCol>
<Col flex1 className="p-4 bg-primary-100 rounded">
<Text semibold>Column 1</Text>
<Text>Horizontal on desktop, stacked on tablet and below.</Text>
</Col>
<Col flex1 className="p-4 bg-primary-100 rounded">
<Text semibold>Column 2</Text>
<Text>Resize to see the responsive behavior.</Text>
</Col>
</Stack>

As a Form Container

Stack's built-in padding makes it a natural container for a form — each Label becomes a row with its input, and the Stack provides the vertical rhythm and outer breathing room without any extra wrapper.

Sign in

Remember me

react-icon
<Stack border rounded className="max-w-sm">
<Title>Sign in</Title>
<Label>
Email
<Input type="email" placeholder="you@example.com" />
</Label>
<Label>
Password
<Input type="password" placeholder="********" />
</Label>
<Row>
<Checkbox />
<Text sm>Remember me</Text>
</Row>
<Button filled>Sign in</Button>
</Stack>

As Link

Add href to render the Stack as an <a> tag — useful for hero cards and large clickable surfaces. A keyboard focus-visible outline auto-renders so the link is reachable via Tab; opt out with noFocusVisible.

react-icon
<Stack href="#get-started" border rounded itemsStart className="max-w-md">
<Zap size={28} />
<PageTitle>Get started in minutes</PageTitle>
<Text>Install the package, drop in ThemeProvider, and start shipping.</Text>
<Button filled>Read the guide</Button>
</Stack>

Next.js Link Integration

Use the tag prop to render the Stack as a Next.js Link for client-side navigation.

react-icon
import Link from 'next/link';
import { Stack, PageTitle, Text, Button } from '@vaneui/ui';
<Stack href="/docs/getting-started" tag={Link} border rounded itemsStart>
<PageTitle>Get started in minutes</PageTitle>
<Text>Install the package, drop in ThemeProvider, and start shipping.</Text>
<Button filled>Read the guide</Button>
</Stack>

Stack Props

PropCategoryDefaultDescription
accent

Appearance

Accent color appearance (rose)

brand

Appearance

Brand color appearance (blue)

danger

Appearance

Danger color appearance (red)

info

Appearance

Info color appearance (cyan)

inherit

Appearance

Inherit appearance from parent — suppresses own data-appearance/data-variant, uses parent's CSS variables

link

Appearance

Link color appearance (blue, for hyperlinks)

primary

Appearance

Primary color appearance (gray)

secondary

Appearance

Secondary color appearance (gray)

success

Appearance

Success color appearance (green)

tertiary

Appearance

Tertiary color appearance

warning

Appearance

Warning color appearance (amber)

desktopCol

Breakpoint

Switch to column layout on desktop and below (max-desktop: 80rem)

mobileCol

Breakpoint

Switch to column layout on mobile and below (max-mobile: 48rem)

tabletCol

Breakpoint

Switch to column layout on tablet and below (max-tablet: 64rem)

flex1

Flex

Take up remaining space (= `flex-1`, i.e. `flex: 1 1 0%`)

flexAuto

Flex

Grow but respect intrinsic size (= `flex-auto`, i.e. `flex: 1 1 auto`)

flexNone

Flex

Don't grow and don't shrink (= `flex-none`, i.e. `flex: none`)

noPadding

Padding

Disable internal padding

padding

Padding

Enable internal padding

paddingX

Padding

Enable only horizontal padding

paddingY

Padding

Enable only vertical padding

pill

Shape

Fully rounded corners (circular)

rounded

Shape

Medium rounded corners (default)

sharp

Shape

No rounded corners (square)

noShrink

Shrink

Prevent the flex item from shrinking below its content size (= `shrink-0`)

lg

Size

Large size

md

Size

Medium size (default)

sm

Size

Small size

xl

Size

Extra large size

xs

Size

Extra small size

textCenter

Text Align

Align text to center

textJustify

Text Align

Justify text

textLeft

Text Align

Align text to left

textRight

Text Align

Align text to right

filled

Variant

Filled variant - solid background with contrasting text color

ghost

Variant

Ghost variant - transparent background, no border, appearance-colored text, tinted hover background

outline

Variant

Outline variant - transparent background with border and colored text (default)

Layout & utility props (gap, padding, hide, items, justify, ...) — documented on Common Props
PropCategoryDefaultDescription
border

Border

Enable border on all sides

borderB

Border

Enable border on bottom

borderL

Border

Enable border on left

borderR

Border

Enable border on right

borderT

Border

Enable border on top

borderX

Border

Enable border on left and right

borderY

Border

Enable border on top and bottom

noBorder

Border

Disable all borders

block

Display

Block display - takes full width, new line

contents

Display

Contents display - element's box is removed, children display as if parent didn't exist

flex

Display

Flex display - flexbox container

grid

Display

Grid display - CSS grid container

hidden

Display

Hidden display - element is not visible

inline

Display

Inline display - flows with text

inlineBlock

Display

Inline-block display - inline but with block properties

inlineFlex

Display

Inline-flex display - inline flexbox container

inlineGrid

Display

Inline-grid display - inline grid container

table

Display

Table display - behaves like table element

tableCell

Display

Table-cell display - behaves like td element

column

Flex Direction

Flex direction column (vertical)

columnReverse

Flex Direction

Flex direction column-reverse

row

Flex Direction

Flex direction row (horizontal)

rowReverse

Flex Direction

Flex direction row-reverse

focusVisible

Focus Visible

Enable focus-visible outline

noFocusVisible

Focus Visible

Disable focus-visible outline

gap

Gap

Enable gap spacing between children

noGap

Gap

Disable gap spacing

hAuto

Height

Set height to auto

hFit

Height

Set height to fit-content

hFull

Height

Set height to 100%

hScreen

Height

Set height to 100vh (viewport height), removes max-height constraint

desktopHide

Hide

Hide element on desktop devices and below (max-desktop: 80rem)

mobileHide

Hide

Hide element on mobile devices and below (max-mobile: 48rem)

tabletHide

Hide

Hide element on tablet devices and below (max-tablet: 64rem)

itemsBaseline

Items

Align items to baseline

itemsCenter

Items

Align items to center

itemsEnd

Items

Align items to end (bottom/right)

itemsStart

Items

Align items to start (top/left)

itemsStretch

Items

Stretch items to fill container

justifyAround

Justify

Distribute items with space around them

justifyBaseline

Justify

Align items along their baseline on main axis

justifyBetween

Justify

Distribute items with space between them

justifyCenter

Justify

Center items along the main axis

justifyEnd

Justify

Pack items toward the end of the main axis

justifyEvenly

Justify

Distribute items with equal space around them

justifyStart

Justify

Pack items toward the start of the main axis

justifyStretch

Justify

Stretch items to fill the main axis

overflowAuto

Overflow

Auto overflow - show scrollbars if needed

overflowClip

Overflow

Clip overflow - hard clip without scrollbars

overflowHidden

Overflow

Hidden overflow - clip content without scrollbars

overflowScroll

Overflow

Scroll overflow - always show scrollbars

overflowVisible

Overflow

Visible overflow - content extends beyond bounds

overflowXAuto

Overflow

Auto overflow on X-axis only

overflowXClip

Overflow

Clip overflow on X-axis only

overflowXHidden

Overflow

Hidden overflow on X-axis only

overflowXScroll

Overflow

Scroll overflow on X-axis only

overflowXVisible

Overflow

Visible overflow on X-axis only

overflowYAuto

Overflow

Auto overflow on Y-axis only

overflowYClip

Overflow

Clip overflow on Y-axis only

overflowYHidden

Overflow

Hidden overflow on Y-axis only

overflowYScroll

Overflow

Scroll overflow on Y-axis only

overflowYVisible

Overflow

Visible overflow on Y-axis only

absolute

Position

Absolute positioning

fixed

Position

Fixed positioning

relative

Position

Relative positioning

static

Position

Static positioning

sticky

Position

Sticky positioning

responsive

Responsive

Enable responsive sizing - uses breakpoint-specific classes for font size, padding, and gap

reverse

Reverse

Reverse the order of children

noRing

Ring

Disable focus ring

ring

Ring

Enable focus ring

noShadow

Shadow

Disable drop shadow

shadow

Shadow

Enable drop shadow

transparent

Transparent

Disable background color - makes component background transparent

wAuto

Width

Set width to auto

wFit

Width

Set width to fit-content

wFull

Width

Set width to 100%

wScreen

Width

Set width to 100vw (viewport width), removes max-width constraint

flexNoWrap

Wrap

Force flex items to stay on single line (may overflow)

flexWrap

Wrap

Allow flex items to wrap to new lines when container is too narrow

flexWrapReverse

Wrap

Wrap flex items in reverse order (last items wrap first)