Chakra UI provides a range of flexible and composable components that can be used to build complex layouts. Alignment and how to position components in a webpage are frequent questions, so I wanted to paste out here some examples to get started.
Introduction
For the Chakra UI components we are going to talk about, knowing about CSS flexbox is a plus. It’s used to display and style the Chakra UI component and can be passed as props for finer control. Here are the main libraries to install:
yarn add react @chakra-ui/react @emotion/react @emotion/styled framer-motion
Chakra UI is to be used with react, so you will want to be familiarized with it. While it can be used without any framework, it may require some boilerplate to be able to start your frontend application (like with webpack/babel setup). Another way is to use a framework like Next.js, Gatsby or one of the available options in the Chakra UI’s documentation to get you started.
Components
You can test the Chakra UI with an example component that you can place within your project. Here is the skeleton, so you can pass the snippet from this article within it to test it out:
import React from 'react';
import { Box, Divider, Flex, HStack, Spacer, StackDivider, VStack } from '@chakra-ui/react';
export const Example = (): React.JSX.Element => {
return (
<Box margin={4} padding={4} border="1px solid lightgray">
{/* Paste the snippet here*/}
</Box>
);
};
The Box
component used here has some default styling to it makes the examples render more visibly in the page.
It is not mandatory but does highlight the snippet when trying it locally.
Now I’ll go into the example, skipping the React component boilerplate and imports since you can use this example as a reference.
Using Flexbox with Chakra UI
Flex
The Flex component is a wrapper around the CSS flexbox properties.
<Flex direction="row" justify="space-between" align="center">
<Box w="100px" h="50px" bg="tomato"/>
<Box w="100px" h="50px" bg="dodgerblue"/>
<Box w="100px" h="50px" bg="orange"/>
</Flex>
Let’s look at the props:
- The
direction
takes the same input as the cssflex-direction
row
/reverse-row
for left to right or right to left row.column
/reverse-column
for top to bottom or bottom to top column.
- The
justify
takes the same input as the cssjustify-content
start
/end
/center
to have the content at the start, end or center of the container.space-between
to have the content spaced in the container from start to endspace-around
to have the content centered with space around them.
- The
align
takes the same input as the cssalign-items
start
/end
/center
/stretch
/baseline
to align the items in the opposite direction of the flex direction.
- The css
align-content
used to align the lines in the container is not available as a props but can be reached via direct css styling.<Flex css={{ alignContent: 'space-between' }} />
The advantages of using Flex
or Box
is that they will automatically work as flex object and display in a predictive
way.
While they remove some of the CSS configuration necessary, they will still need some props to be passed to for optimal use.
Spacer
A spacer can be used in a Flex
component to add space between the children.
It can be added using:
<Spacer />
If you know about flexbox, it will just add more space between elements in the flex container.
This is a shorthand for adding a Box
with a flex-grow
of 1
.
Stacks
Now Chakra UI provides a Stack component that is a wrapper around the Flex
component.
So you can do horizontal or vertical Flex components named as HStack
and VStack
.
Stack
The Stack
doesn’t have a direction and is a great neutral element that can be used within your UI.
The children are position in a column by default, stacking on top of each other.
<Stack alignItems={{ base: 'stretch', md: 'end' }}> </Stack>
Using a Stack
, a Box
or a Flex
component, there are no real guidelines.
It’s more about what you are trying to achieve.
The key difference between a
Stack
and aFlex
is that unlike theFlex
, theStack
component won’t span the entire width of the container.
HStack
Now the HStack
is an abstraction of a Flex
component where the elements are aligned horizontally.
This removes a bit of the flexbox properties’ boilerplate.
Create one with a text and an icon as:
<HStack>
<Icon as={PiTrash} />
<Text fontWeight="bold">Delete</Text>
</HStack>
It will display as:
🗑️ Delete
They should be already horizontally aligned, but you can still pass the justify
and align
props to it.
- Using
justify={'end'}
will make the element displayed on the right of the HStack instead of starting from the left.
Here is a diagram of how a HStack
would look:
flowchart LR
subgraph Hstack
c1[component]
c2[component]
c3[component]
end
subgraph Hstack2[Hstack]
c4[component]
c5[component]
c6[component]
end
VStack
The VStack
is an abstraction of a Flex
component where the elements are aligned vertically.
This removes a bit of the flexbox properties’ boilerplate.
Create one with a title and a text as:
<VStack align={'start'} flex={1}>
<Heading as="h2">
Title
</Heading>
<Text>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam commodo dictum turpis, in feugiat ex tincidunt vitae.
Quisque sit amet commodo erat. In laoreet diam in lacinia temp
</Text>
</VStack>
By default, the VStack will centre the element in the middle of the stack.
- Using
align={'start'}
will make the element starts on the right of the VStack.
Using a Text
component which acts as a p
element and a Heading
component whic acts as a h2
element,
it will render as:
## Title
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam commodo dictum turpis, in feugiat ex tincidunt vitae.
Quisque sit amet commodo erat. In laoreet diam in lacinia temp
And to better illustrate it, I have added a diagram of how a VStack would look:
flowchart LR
Container:::transparent
classDef transparent fill:transparent,stroke:transparent, color:transparent;
subgraph Container
direction TB
subgraph Vstack
c1[component]
c2[component]
c3[component]
end
end
subgraph Container
direction TB
subgraph Vstack2[Vstack]
c4[component]
c5[component]
c6[component]
end
end
This should mimic the rendered output of the React component.
Divider
If you need to add a divider between the component, you could play with the border properties of the stacks or the
component within them or use the divider
props that is available in the stack components.
<Stack divider={<StackDivider />} />
But if you don’t need a divider between all components, you could use a Divider
component and insert it where needed.
It is a simple line that can be added between the components.
Here is how you would do it:
// Divider (horizontal by default)
<Divider w={'100%'} />
// Vertical divider
<Divider orientation="vertical" sx={{ height: 'auto', alignSelf: 'stretch' }} />
The vertical divider is trickier than the horizontal one. By default, it’s 1 pixel wide, so it needs to be stretched
to be visible.
The sx
props is used to pass custom styles to the component.
Here is how the Divider would look on a rendered component:
flowchart LR
Container:::transparent
classDef transparent fill:transparent,stroke:transparent, color:transparent;
subgraph Container
direction TB
subgraph Vstack
c1[component]
c2[component]
c3[component]
end
subgraph divider
a:::transparent
b:::transparent
c:::transparent
end
subgraph Vstack2[Vstack]
c4[component]
c5[component]
c6[component]
end
end
I had some fun doing some mermaid diagram to try and represent it all visually. But I guess it doesn’t beat the actual generated examples like the ones you can find in the documentation.
Chakra UI has been really easy to work with and is pretty simple and flexible. I managed to render complex layouts within days, so I would recommend testing it out.