Stack
Stack, HStack, and VStack are higher-level layout components that provide an ergonomic API for building one-dimensional layouts with consistent spacing between elements.
Deprecated Component
The Stack component has been deprecated in v8 and will be removed in v9. Teams using Stack should switch over to the newly enhanced Flex component. A codemod for this change is available in the 8.4.0 release.
Flex DocumentationExamples
Stack
is a higher-level layout component, meaning:
- It's built on top of lower-level components (
Box
andFlex
) - It's opinionated about how it builds layouts.
Stack
has three core opinions that guide its API:
- Space should be equal between child elements
- Space should only exist between child elements
- Children should be semantic elements
Much of layout design is founded on these opinions. Whether its creating lists of navigation links, groups of cards, or collections of buttons, once you think in stacks, you'll see them everywhere.
Basic Example
Stack
is a composable component that's helpful for creating layouts with equal spacing between
elements. It can create horizontal or vertical stacks of elements.
The most important distinction to make with
Stack
is that it is not a grid. Grid components are able to align items along two dimensions (rows and columns), andStack
is only built to support one dimension (rows or columns). That said, you can nest horizontal and verticalStack
components to create grid-like layouts.
Stack
uses CSS pseudo-classes to apply margin to child elements. This makes it really simple to
get consistent spacing between child elements without much manual effort. Below is a basic example.
Note that Stack
does not add any space above or below the child elements. This helps your element
fit nicely within their containers.
Use this approach when:
- You want consistent space between child elements
- You don't need to apply custom margin to child elements
- Specifically
marginLeft
/marginInlineStart
for horizontal stacks andmarginTop
for vertical stacks
- Specifically
- You don't want to add extra markup to wrap child elements
Setting Direction
The direction of the child elements is set with the flexDirection
prop. This prop supports four
directions: column
, column-reverse
, row
, and row-reverse
. By default, it will set the
direction to row
as is consistent with the CSS Flexbox spec.
Note:
flex-direction
and other CSS Flexbox attributes support bidirectionality (LTR and RTL) automatically. You don't need to think about switching directions for localization.
Note:
spacing
also supports bidirectionality automatically. This means you don't need to think about it for localization as long as you properly pass thedirection
to thetheme
object un
Setting Space
The space between child elements is set with the spacing
prop, which supports all space token and
string values. Stack
intentionally only sets space between elements and never outside. For
example: a vertical stack of three elements would only have margin added to the top of the second
and third child elements. Keeping space between elements makes building layouts more block-like and
predictable.
Managing Child Elements
There are three ways to manage space between child elements with Stack
.
- Implicit spacing applied directly to child elements (default behavior)
- Implicit wrapping child elements with
shouldWrapChildren
- Explicit wrapping child elements with
Stack.Item
s.
Each approach has its own benefits and limitations, which are discussed in further detail below. We
chose to implicitly apply spacing to child elements as the default behavior because it requires the
least overhead to implement and should support most use cases. The other approaches act as escape
hatches for when the default behavior becomes forced. Should you find none of these approaches work
for your use case, we recommend using Flex
instead of Stack
, which will provide you with more
flexibility.
Valid Children
Because Stack
applies styles to children, it requires its immediate children to be valid child
elements. For example, text outside of an HTML tag would not render if it was an immediate Stack
child. Here's an example snippet:
const ValidChildrenExample = () => {return (<Stack flexDirection="row" spacing="s">This text will not render. Don't do this.<p>This text will render.</p><span>This text will also render.</span></Stack>);};
Grid-like Layouts
You can nest vertical and horizontal Stack
s to create grid-like layouts. Here are three horizontal
Stack
s nested within a vertical Stack
. The fourth row is a single Flex
component.
Small Containers
You can also use Stack
to manage smaller layouts, such as within Cards.
Stack
Stack provides a simple API for managing consistent space between elements in one-dimensional layouts. In this Card example, we are setting extra-small spacing the heading, body text, and button elements.
HStack
HStack
works identically to Stack
but is limited to only row
and row-reverse
directions. It
defaults to row
if no flexDirection
is provided.
Note:
HStack
supports bidirectionality automatically. This means that you won't need to switch the direction or spacing for localization. The direction switching is handled by the CSS Flexbox spec, and the spacing will flip direction based on thedirection
provided in thetheme
object.
In this example, HStack
is placing three cards in a row with small spacing between them.
Diavola
sauce, smoked mozzarella, pepperoni, basil, chili flake
Four Cheese
mozzarella, gorgonzola, smoked mozzarella, parmesan, garlic oil
Veggie
sauce, mozzarella, artichokes, roasted red peppers, broccolini
VStack
VStack
works identically to Stack
but is limited to only column
and column-reverse
directions. It defaults to column
if no flexDirection
is provided.
In this example, VStack
is placing three cards in a column with small spacing between them.
Diavola
sauce, smoked mozzarella, pepperoni, basil, chili flake
Four Cheese
mozzarella, gorgonzola, smoked mozzarella, parmesan, garlic oil
Veggie
sauce, mozzarella, artichokes, roasted red peppers, broccolini
shouldWrapChildren and Stack.Item
A side-effect of Stack
's pseudo-classes is an increased style specificity. This specificity can
override the child element's margin styles. If that creates a problem, there are two recommended
options available:
- Use the
shouldWrapChildren
prop (implicit option) - Use
Stack.Item
(explicit option)
shouldWrapChildren
The shouldWrapChildren
prop will implicitly wrap each child in a Stack.Item
component (which is
a Box
) and apply the margin to it instead of the child element provided. This allows you to
control the margin of the child elements you provide and avoiding style collisions. The trade-off is
that you do not have direct access to the Stack.Item
being rendered. If having access to that
element is necessary, using Stack.Item
explicitly (as described below) could be the best solution.
The example below is a bit contrived but has enough information to convey the point. In this
scenario, we have a horizontal stack of SecondaryButton
s that render an icon, but they are
visually divided into separate groupings. The navigational buttons are on the left, and the
additional actions are spaced slightly further to the right. You could use two separate horizontal
stacks here to achieve the same result, but you could also use shouldWrapChildren
and then put
additional margin only where needed. Either approach would be fine; it's a matter of personal
preference.
Use this approach when:
- You want consistent space between child elements
- You need to apply custom margin to particular children
- Wrapping each child element won't create issues with other semantic elements
- You don't want to explicitly add extra markup to wrap child elements
Stack.Item
Sometimes inserting implicit wrapper elements can be problematic when you need access to those
elements. In those situations, shouldWrapChildren
is not the best choice, and you should opt for
wrapping children in Stack.Item
s. A Stack.Item
is a Box
with some preset styles which can be
overridden if needed.
In the example below, we wanted to keep our li
elements as direct children of the ul
stack. So
we're wrapping each of the links with Stack.Item
s, casting them as li
s and applying custom
styles to each. This would not be possible with shouldWrapChildren
.
Use this approach when:
- You want consistent space between child elements
- You need to have direct access to
Stack.Item
wrappers - Wrapping each child element won't create issues with other semantic elements
Stack Props
StackStyleProps
Name | Type | Description | Default |
---|---|---|---|
spacing |
| sets space values between child elements (bidirectional support) | |
flexDirection |
| sets the direction for the stack | |
shouldWrapChildren | boolean | when |
Stack
extends
flex container style props and Box
style props.
Can't Find What You Need?
Check out our FAQ section which may help you find the information you're looking for.
FAQ Section