Stack
Stack layers children on top of each other, mirroring Flutter's Stack widget. It provides precise control over absolute and relative positioning, z-index ordering, and alignment using a declarative API built on CSS positioning.
import { Stack } from '@dynshift/layr';
<Stack style={{height:'10vh', width:'10vw'}}>
<div>Background Layer</div>
<div>Middle Layer</div>
<div>Top Layer</div>
</Stack>
NOTE: Previews are not depiction of actual website output.
Children are painted in order: first child at the bottom, last child on top.
<Stack style={{width:'20vw', height:'20vh'}}>
<Container
width={200}
height={200}
decoration={{ color: '#eb1660' }}
/>
<Container
width={150}
height={150}
decoration={{ color: '#3b82f6' }}
/>
<Container
width={100}
height={100}
decoration={{ color: '#10b981' }}
/>
</Stack>
NOTE: Previews are not depiction of actual website output.
1b. With Positioned Children
Use Positioned to control exact placement.
import { Stack, Positioned } from '@dynshift/layr';
<Stack style={{ width: 300, height: 200 }}>
<Container decoration={{ color: '#f3f4f6' }} />
<Positioned top={10} left={10}>
<span>Top Left</span>
</Positioned>
<Positioned bottom={10} right={10}>
<span>Bottom Right</span>
</Positioned>
</Stack>
NOTE: Previews are not depiction of actual website output.
The alignment prop controls how non-positioned children are aligned within the stack.
<Stack alignment="topLeft" style={{width:'20vw', height:'20vh'}}>
<Container width={200} height={200} decoration={{ color: '#f3f4f6' }} />
<Container width={100} height={100} decoration={{ color: '#eb1660' }} />
</Stack>
NOTE: Previews are not depiction of actual website output.
Center all non-positioned children.
<Stack
alignment="center"
style={{width:'20vw', height:'20vh'}}
>
<Container
width={200}
height={200}
decoration={{ color: '#333' }}
/>
<span>Centered Text</span>
</Stack>
NOTE: Previews are not depiction of actual website output.
2c. All Alignment Options
• topLeft — Top-left corner (default)
• topCenter — Top edge, horizontally centered
• topRight — Top-right corner
• centerLeft — Left edge, vertically centered
• center — Centered both horizontally and vertically
• centerRight — Right edge, vertically centered
• bottomLeft — Bottom-left corner
• bottomCenter — Bottom edge, horizontally centered
• bottomRight — Bottom-right corner
The fit prop controls how non-positioned children are sized.
Children are allowed to be as large as they want.
import { StackFit } from '@dynshift/layr';
<Stack
fit={StackFit.loose}
style={{width:'20vw', height:'20vh'}}
>
<Container
width={150}
height={150}
decoration={{ color: '#eb1660' }}
/>
<span>Content</span>
</Stack>
NOTE: Previews are not depiction of actual website output.
• StackFit.loose — Children size themselves (default)
• StackFit.expand — Fill all available space
• StackFit.passthrough — Minimal size
Control how overflowing content is handled.
Clip without anti-aliasing.
import { Clip } from '@dynshift/layr';
<Stack clipBehavior={Clip.hardEdge} style={{ width: 200, height: 200 }}>
<Container width={300} height={300} decoration={{ color: '#eb1660' }} />
</Stack>
NOTE: Previews are not depiction of actual website output.
Clip with anti-aliasing for smoother edges.
<Stack clipBehavior={Clip.antiAlias} style={{ width: 200, height: 200 }}>
<img src="/eg-bg.jpg" alt="Clipped" />
</Stack>
NOTE: Previews are not depiction of actual website output.
Do not clip overflowing content.
<Stack clipBehavior={Clip.none}>
<Container width={300} height={300} decoration={{ color: '#3b82f6' }} />
</Stack>
NOTE: Previews are not depiction of actual website output.
• Clip.hardEdge — Clip without anti-aliasing (default)
• Clip.antiAlias — Clip with anti-aliasing
• Clip.antiAliasWithSaveLayer — Clip with anti-aliasing and save layer
• Clip.none — No clipping
5. Text Direction (RTL Support)
Control alignment behavior for right-to-left languages.
Normal left-to-right behavior.
import { TextDirection } from '@dynshift/layr';
<Stack
alignment="topLeft"
textDirection={TextDirection.ltr}
style={{ width: 200, height: 200 }}
>
<span>Left aligned in LTR</span>
</Stack>
NOTE: Previews are not depiction of actual website output.
Right-to-left behavior (mirrors alignment).
<Stack
alignment="topLeft"
textDirection={TextDirection.rtl}
style={{ width: 200, height: 200 }}
>
<span>Right aligned in RTL</span>
</Stack>
NOTE: Previews are not depiction of actual website output.
When textDirection is rtl, topLeft becomes topRight and vice versa.
Notification badge positioned on top-right corner.
<Stack style={{ width: 64, height: 64 }}>
{}
<Container
padding={32}
decoration={{
image: { image: '/eg-bg.jpg', fit: 'cover' },
shape: BoxShape.circle,
}}
/>
{}
<Positioned top={0} right={0}>
<Container
width={20}
height={20}
decoration={{
color: '#ef4444',
shape: BoxShape.circle,
border: {
width: 2,
color: '#ffffff',
},
}}
>
<Centre>
<span style={{ color: 'white', fontSize: '0.75rem', fontWeight: 700 }}>
3
</span>
</Centre>
</Container>
</Positioned>
</Stack>
NOTE: Previews are not depiction of actual website output.
Video thumbnail with centered play button.
<Stack alignment="center" style={{ width: 640, height: 360 }}>
{}
<Container
padding={320}
decoration={{
image: {
image: '/eg-bg.jpg',
fit: 'cover',
},
}}
/>
{}
<Container
decoration={{
color: 'rgba(0, 0, 0, 0.3)',
}}
/>
{}
<Container
width={80}
height={80}
decoration={{
color: 'rgba(255, 255, 255, 0.95)',
shape: BoxShape.circle,
}}
style={{ cursor: 'pointer' }}
>
<Centre>
<svg width="32" height="32" viewBox="0 0 24 24" fill="none">
<path d="M8 5v14l11-7z" fill="#eb1660" />
</svg>
</Centre>
</Container>
</Stack>
NOTE: Previews are not depiction of actual website output.
Semi-transparent watermark on bottom-right.
<Stack style={{ width: 800, height: 600 }}>
{}
<img src="/eg-bg.jpg" alt="Photo" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
{}
<Positioned top={50} left={50}>
<Container
padding={12}
decoration={{
color: 'rgba(0, 0, 0, 0.6)',
borderRadius: 6,
}}
>
<span style={{ color: 'white', fontSize: '0.875rem', fontWeight: 600 }}>
© 2025 Your Brand
</span>
</Container>
</Positioned>
</Stack>
NOTE: Previews are not depiction of actual website output.
6d. Status Indicator on Icon
Online status indicator on avatar.
<Stack style={{ width: 48, height: 48 }}>
{}
<Container
padding={24}
decoration={{
image: { image: '/eg-bg.jpg', fit: 'cover' },
shape: BoxShape.circle,
}}
/>
{}
<Positioned bottom={2} right={2}>
<Container
width={14}
height={14}
decoration={{
color: '#10b981',
shape: BoxShape.circle,
border: { width: 2, color: '#ffffff' },
}}
/>
</Positioned>
</Stack>
NOTE: Previews are not depiction of actual website output.
<Stack style={{ width: 600, height: 400 }}>
{}
<Container
padding={200}
decoration={{
image: { image: '/eg-bg.jpg', fit: 'cover' },
}}
foregroundDecoration={{
gradient: {
type: 'linear',
colors: ['rgba(219, 17, 17, 0.6)', 'rgba(51, 201, 126, 0.6)'],
begin: 'to bottom',
},
}}
/>
{}
<Container
padding={200}
style={{ clipPath: 'inset(0 50% 0 0)' }}
decoration={{
image: { image: '/eg-bg.jpg', fit: 'cover' },
}}
/>
{}
<Positioned top={0} bottom={0} left="50%" style={{ transform: 'translateX(-50%)' }}>
<Container
width={4}
decoration={{ color: '#ffffff' }}
/>
</Positioned>
</Stack>
NOTE: Previews are not depiction of actual website output.
Toast notification on top-right.
<Stack fit={StackFit.expand} style={{ minHeight: '100vh' }}>
{}
<div style={{ padding: 20, backgroundColor: '#f5f5f5', color: '#000' }}>Your app content</div>
{}
<Positioned top={20} right={20}>
<Container
width={320}
padding={16}
decoration={{
color: '#333',
borderRadius: 8,
boxShadow: [{
color: 'rgba(0, 0, 0, 0.15)',
offset: { dx: 0, dy: 4 },
blurRadius: 16,
}],
}}
>
<Row spacing={12} crossAxisAlignment={CrossAxisAlignment.center}>
<Container
width={40}
height={40}
decoration={{
color: '#10b981',
shape: BoxShape.circle,
}}
>
<Centre>
<span style={{ color: 'white', fontSize: '1.25rem' }}>✓</span>
</Centre>
</Container>
<Column crossAxisAlignment={CrossAxisAlignment.start} spacing={4} style={{ flex: 1 }}>
<span style={{ fontWeight: 600 }}>Success!</span>
<span style={{ color: '#6b7280', fontSize: '0.875rem' }}>
Your changes have been saved.
</span>
</Column>
</Row>
</Container>
</Positioned>
</Stack>
NOTE: Previews are not depiction of actual website output.
Stack follows Flutter's layout specification:
• Non-positioned children are positioned according to alignment
• Stack sizes itself to contain all non-positioned children
• Positioned children are placed relative to stack edges
• Children are painted in order (first = bottom, last = top)
Important: Stack children are painted in order. To change z-index, reorder children in the array.
Children are automatically assigned z-index based on their order.
<Stack style={{ width: 200, height: 200 }}>
<div>Layer 1 (z-index: 0)</div>
<div>Layer 2 (z-index: 1)</div>
<div>Layer 3 (z-index: 2)</div>
</Stack>
NOTE: Previews are not depiction of actual website output.
To change stacking order, reorder the children.
<Stack
style={{ width: 200, height: 200 }}
className="bg-gray-100 rounded-lg p-4">
<span>Styled with Tailwind</span>
</Stack>
<Stack
style={{
backgroundColor: '#f3f4f6',
borderRadius: '8px',
padding: '16px'
}}
>
<span>Custom styles</span>
</Stack>
Stack is fully typed with comprehensive IntelliSense support.
import type { StackProps } from '@dynshift/layr';
import { Stack, StackFit, Clip } from '@dynshift/layr';
const LayeredCard: React.FC<StackProps> = (props) => {
return (
<Stack
alignment="center"
fit={StackFit.loose}
clipBehavior={Clip.hardEdge}
{...props}
/>
);
};
| Prop | Type | Default | Description |
|---|
| children | ReactNode | — | Widgets to stack (first = bottom, last = top) |
| alignment | StackAlignment | 'topLeft' | How to align non-positioned children |
| fit | StackFit | loose | How to size non-positioned children |
| textDirection | TextDirection | ltr | Text direction for alignment resolution |
| clipBehavior | Clip | hardEdge | How to clip overflowing content |
| className | string | '' | Additional CSS classes |
| style | CSSProperties | {} | Custom inline styles |
| id | string | — | HTML id attribute |
| onTap | () => void | — | Click handler (Flutter-style) |
| onClick | () => void | — | Click handler |
| Value | Description |
|---|
| 'topLeft' | Top-left corner (default) |
| 'topCenter' | Top edge, centered horizontally |
| 'topRight' | Top-right corner |
| 'centerLeft' | Left edge, centered vertically |
| 'center' | Centered both horizontally and vertically |
| 'centerRight' | Right edge, centered vertically |
| 'bottomLeft' | Bottom-left corner |
| 'bottomCenter' | Bottom edge, centered horizontally |
| 'bottomRight' | Bottom-right corner |
| Value | Behavior | Description |
|---|
| loose | Sized by children | Children size themselves (default) |
| expand | Fill parent | Fill all available space |
| passthrough | Minimal size | Minimal size |
| Value | Behavior |
|---|
| hardEdge | Clip without anti-aliasing (default) |
| antiAlias | Clip with anti-aliasing |
| antiAliasWithSaveLayer | Clip with anti-aliasing and save layer |
| none | No clipping |
| Value | Description |
|---|
| ltr | Left-to-right (normal) |
| rtl | Right-to-left (mirrors alignment) |
• Positioned — Precise positioning within Stack
• Positioned Fill — Fill-positioned children