Layout
Layouts help to create a visually consistent experience across Workday products. At the foundation of layouts is the 12 column Canvas grid. Use this to guide your decisions when laying out content within your product.
Grid Anatomy
- Margins: The space at the outer edges of the grid, should always be of equal fixed width.
- Columns: Span the width of the content, use this to align your content correctly.
- Gutters: The space between columns that help separate content.
12 Column Grid
The Canvas grid system uses 12 columns. We chose the 12 column grid system because it is easy to divide 12 columns into halves, thirds, fourths, and sixths when designing for different screen sizes. We recommend reducing the number of columns as the screen width reduces as illustrated below. Check out our Responsive Layouts for recommended sizes.
Usage Guidance
The Grid system should be used when designing any layout within your product. If you think of your UI elements like blocks then these blocks can span across the 12 column grid in any number of ways as illustrated below. The 12 column grid system gives you a lot of flexibility when arranging UI elements.
Not all UI elements within your layout need to align with the column. As long as the parent element aligns to the assigned number of columns, that’s okay!
The cards within the above container do not need to align with the layout columns. You can use the 8pt grid to align the cards.
Responsive Layouts
Responsive layouts change the appearance of a layout, depending on the screen size and orientation of the device being used to view it. We recommend using the following grids to cater for these different screen sizes below.
Small
320px - 767px
Number of columns: 4 Margins: 16px Gutter: 16px
Used for mobile size screens
To accommodate a 3 panel layout on mobile you can add a separate 12 column grid with a margin of 16px and gutter of 16px

Medium
768px - 1023px
Number of columns: 8 Margins: 40px Gutter: 24px
Used for tablet size screens

Large
1024px - 1439px
Number of columns: 12 Margins: 40px Gutter: 32px
Used for desktop and small laptop size screens

Extra Large
1440px+
Number of columns: 12 Margins: 80px Gutter: 40px
Used for large desktop size screens
For extra large screens we recommend that you apply a Max-Width of 1440px for the main page content.

Breakpoint | Value | Columns | Margin | Gutter |
---|---|---|---|---|
Small | 320px | 4 | 16px | 16px |
Medium | 768px | 8 | 40px | 24px |
Large | 1024px | 12 | 40px | 32px |
Extra Large | 1440px | 12 | 80px | 40px |
Layout Regions
Grids should always be used to layout your designs, even when working with different layout regions. Grids give you greater control over different regions and how you can position UI elements within your screen layout.
Grids used to accommodate layouts with left and right side panels regions that overlays the main page content
In the cases illustrated above, side panels can reduce the width of the main page content or overlay the page content. Grids of varying columns e.g 4, 8 or 12 can be used to accommodate your layout, but we recommend reducing the number of columns as the width decreases in order to prevent the layout becoming cluttered.
Density
The grid system can help you design for both high and low density layouts. The important thing to remember when working with density is to increase the margin and gutter space on high density layouts and decrease the margin and gutter space on low density layouts. This allows the user to easily scan groups of content.
When to Use
- To help you make decisions when designing high or low density layouts.
- Create visual hierarchy and rhythm in your layouts.
- Create consistent layouts across your product.
Flex Examples
Basic Example
Canvas Principles
Empower over Enforce
Encourage our user's expression. Stay out of the way and provide them with the tools and resources to build their vision.
Evolution over Perfection
Nothing is ever perfect – embrace that. Make educated assumptions, validate and test our decisions, then iterate! Aim of continous rather than perfect solutions.
Simple over Clever
Simple solutions invite the user in - clever solutions invite complexity. Make the system easy and predictable, and progressively disclose advanced functionality.
Everyone over Every One
Each piece of the system is designs and built to be accessible, while still providing the best experience for all consumers. But not if something is focused on a single use case and negates the usability for others.
Rows and Columns
You can nest Flex
components to build layouts with rows and columns.
Small Containers
You can also use Flex
to create layouts within smaller containers, such as this card example
below:
Learn about Flex
Complete this task when you have a functional understanding of Flex.
Flex vs. Box
Flex
is built with Box
and has access to all BoxProps
. The main differences between Box
and
Flex
are:
Flex
is set todisplay: flex
by default- The
display
prop is limited toflex
andinline-flex
Flex
has access to flex container properties.
In short, use Flex
when you need a flex container to build layouts with CSS Flexbox, and use Box
when you need a simple container. It's also important to note that Flex
has no real opinion about
how to build layouts outside of the CSS Flexbox spec. Its unopinonated nature allows it to be
composed into many different components.
Flex Props
As previously mentioned, Flex
is built on top of Box
and has access to all its props, including
flex item properties. But Flex
adds
flex container properties
through style props as well. There are seven flex container props:
Name | Type | Default | Description |
---|---|---|---|
alignItems | PropertyAlignItems | undefined | sets `align-items` property | |
alignContent | PropertyAlignContent | undefined | sets `align-content` property | |
display | "flex" | "inline-flex" | undefined | 'flex' | sets `display` property |
justifyItems | PropertyJustifyItems | undefined | sets `justify-items` property | |
justifyContent | PropertyJustifyContent | undefined | sets `justify-content` property | |
flexWrap | PropertyFlexWrap | undefined | sets `flex-wrap` property | |
flexDirection | PropertyFlexDirection | undefined | sets `flex-direction` property |
Flex Props (Exhaustive List)
Name | Type | Default | Description |
---|---|---|---|
alignItems | PropertyAlignItems | undefined | sets `align-items` property | |
alignContent | PropertyAlignContent | undefined | sets `align-content` property | |
justifyItems | PropertyJustifyItems | undefined | sets `justify-items` property | |
justifyContent | PropertyJustifyContent | undefined | sets `justify-content` property | |
flexWrap | PropertyFlexWrap | undefined | sets `flex-wrap` property | |
flexDirection | PropertyFlexDirection | undefined | sets `flex-direction` property | |
ref | React.Ref<any> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If `as` is set to an element, it will be that element. If `as` is a component, the reference will be to that component (or element if the component uses `React.forwardRef`). | |
as | "symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any> | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using `React.forwardRef` and spread extra props to a root element. |
Stack Examples
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 flakeFour Cheese
mozzarella, gorgonzola, smoked mozzarella, parmesan, garlic oilVeggie
sauce, mozzarella, artichokes, roasted red peppers, broccolinishouldWrapChildren 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
Name | Type | Default | Description |
---|---|---|---|
alignItems | PropertyAlignItems | undefined | sets `align-items` property | |
alignContent | PropertyAlignContent | undefined | sets `align-content` property | |
justifyItems | PropertyJustifyItems | undefined | sets `justify-items` property | |
justifyContent | PropertyJustifyContent | undefined | sets `justify-content` property | |
flexWrap | PropertyFlexWrap | undefined | sets `flex-wrap` property | |
flexDirection | "column" | "column-reverse" | "row" | "row-reverse" | undefined | "row" | sets `flex-direction` property sets the direction for the stack |
spacing * | StackSpacing | sets space values between child elements (bidirectional support) | |
shouldWrapChildren | boolean | undefined | false | when `true` wraps each child element in a `Stack.Item` |
ref | React.Ref<any> | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If `as` is set to an element, it will be that element. If `as` is a component, the reference will be to that component (or element if the component uses `React.forwardRef`). | |
as | "symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any> | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using `React.forwardRef` and spread extra props to a root element. |
Can't Find What You Need?
Check out our FAQ section which may help you find the information you're looking for.
FAQ Section