Layout
Learn how to build application layouts with Hopper using Flex or Grid.
Introduction
Hopper includes layout components to help build applications. The Flex and Grid
components are containers responsible for the layout of their children. Flex
follows the the
CSS flexbox
algorithm, while Grid
implements
CSS grid.
These components provide props with predefined Hopper tokens for sizing, spacing,
and other layout options. You can use Flex
and Grid
together to build different
parts of your application, and even nest them to create more complex layouts.
You should prefer using flex and grid over other CSS layout models. Spacing between components should be managed by parent layout components rather than added directly to the children. This ensures components are composable when reused in different places and that spacing remains consistent.
In addition to Flex
and Grid
, some Hopper components include prebuilt layouts which you can
insert your content into via slots. You can read more about slots in the slots concept page.
Flex
The flexbox layout model is a simple yet versatile method of laying out components in rows and columns. Use it to build vertical or horizontal stacks, simple wrapping grids, and more. The Flex component can be used to create flexbox containers. Any Hopper component can be used as a child within these containers. Flex layouts can be nested to create more complex layouts.
The gap
, rowGap
and columnGap
can be defined with Hopper space tokens
to ensure consistency across applications, and allow the layout to adapt to different devices automatically.
Example
A simple vertical stack, with a gap between each item defined using a Hopper space token.
Learn more
You can learn more about Flex
and see more examples on the Flex page. There are many great resources on the web for learning flexbox as well.
- The MDN guide to flexbox — full walkthrough of flexbox layout.
- A Complete Guide to Flexbox — great reference for all of the properties supported by flexbox.
Grid
CSS grid is a powerful way to lay out elements in two dimensions. It can be used to to build full page application layouts, or smaller user interface elements. It is especially powerful because it allows you to build many types of layouts without extra presentational elements, keeping your code clean and semantic. In addition, grid layouts are automatically mirrored in right-to-left languages.
The Grid component can be used as a container to define a grid layout. Any Hopper component can be used as
a child of a Grid
. The Grid
component extends the CSS syntax to support
defining grids using Hopper-defined dimension tokens.
This ensures that sizing and spacing is consistent between applications, and allows the layout to adapt to different devices
automatically.
Defining grids
There are many ways to define grids, but the simplest is to use the areas
prop to declaratively
specify your layout using named areas. This prop accepts an array of strings which represent rows. Within the rows,
you specify space separated names for grid areas. The children of the Grid
can declare the gridArea
prop, which
places them into these named regions.
In addition, you can define the columns
and rows
props on the Grid
container to specify the widths and heights of the columns and rows respectively. This can be
done using Hopper-defined dimension tokens to ensure they are adaptive on various devices.
The following example shows how you could use Grid
to declare a common application layout, with a header, sidebar,
content area, and footer. Notice how there are no nested layout elements — the layout is entirely declared in the
Grid
and the children simply declare where they should be placed.
Learn more
You can learn more about Grid
and see more examples on the Grid page. There are many great resources on the web for learning CSS grid as well.
- The MDN guide to CSS grid — full walkthrough of grid layout.
- A Complete Guide to Grid — great reference for all of the properties supported by grid.
- The Difference Between Explicit and Implicit Grids — an article that discusses the various ways of defining grids.
Choosing Inline, Stack, or Flex
Use Inline or Stack by default when your layout matches their intent. They are opinionated Flex presets that keep code shorter and more consistent:
Important: Inline
and Stack
do not support the raw justifyContent
or alignItems
props. Instead they expose semantic aliases:
/** An alias for the CSS justify-content property. */ alignX?: FlexProps["justifyContent"]; /** An alias for the CSS align-items property. */ alignY?: FlexProps["alignItems"];
Use alignX
where you would normally use justifyContent
, and alignY
where you would use alignItems
when working with Inline
or Stack
. The underlying Flex
component still uses justifyContent
and alignItems
directly.
Inline
isFlex
withflex-direction: row
,align-items: center
, and a default gap token for horizontal spacing (exposed asalignY="center"
).Stack
isFlex
withflex-direction: column
and a default gap token for vertical spacing.
When to use Inline
You have items in a single horizontal row and shared cross axis alignment: Typical header actions, icon plus label, button groups.
It is fine to tweak one thing such as gap
, alignX
(was justifyContent
in raw flex), or wrap
. If you also need a different cross axis alignment (alignY
) and another structural change, prefer Flex
.
Example:
<Inline gap="inline-sm" alignX="space-between"> <Title /> <Actions /> </Inline>
When to use Stack
You are arranging elements vertically with consistent spacing: Forms, card content, dialog body.
It is fine to tweak one thing such as gap
or alignY
(alias for alignItems
). If you also need direction to flip at a breakpoint or multiple alignment rules, prefer Flex
.
Example:
<Stack gap="stack-md"> <Field /> <Field /> <HelpText /> </Stack>
When to use Flex
You are doing more than a light tweak or you need per child control. Any two or more of the following is a good signal to switch:
- Changing
alignItems
andjustifyContent
together (forInline
/Stack
this would be changing bothalignX
andalignY
), - Mixing
wrap
with custom alignment, - Using
order
,flex grow
orshrink
on children, - Flipping
flex-direction
responsively, - Aligning some children differently from others,
- Asymmetric or breakpoint specific gaps,
- Baseline alignment for text heavy rows.
Example:
<Flex alignItems="flex-start" justifyContent="space-between" gap="inline-lg"> <Avatar size="lg" name="Alexandre" /> <Stack gap="stack-sm" flex={1}> <H3>Alexandre Asselin</H3> <Text variant="body-sm" color="text-secondary"> Staff Software Engineer </Text> </Stack> <Inline gap="inline-sm"> <Button variant="secondary">Message</Button> <Button variant="primary">Connect</Button> </Inline> </Flex>
Practical Rule
Start with Inline
for horizontal rows and Stack
for vertical stacks. If you find yourself changing more than one core knob or applying flex properties to individual children, move to Flex
. One override is fine. Two or more usually means Flex
.
Responsive layout
All props of the Flex and Grid components support object syntax to specify different values for the prop depending on a responsive breakpoint. You can learn more about responsive styles on the Responsive Styles page.