Layouts in Chakra UI

6 September 2023

This post is written primarily for the students in my React Application Workshop, but may be useful for anyone who wants to build layouts in Chakra UI.

Flex

Our first layout component we will look at is the Flex component. The Flex component is essentially a Box with display: flex;. You can use it to make horizontal and vertical layouts. The advantage of this component is that it has these shorthands for Flexbox properties:

  • flexDirection is direction
  • flexWrap is wrap
  • flexBasis is basis
  • flexGrow is grow
  • flexShrink is shrink
  • alignItems is align
  • justifyContent is justify

Experiment in the sandbox below (be sure to read and understand the code):

import { ChakraProvider, Flex, Button } from '@chakra-ui/react'

export default function App() {
  return (
    <ChakraProvider>
      <Flex
        direction="column"
        height="100vh"
        align="center"
        justify="space-evenly"
      >
        <Button colorScheme="teal">Button 1</Button>
        <Button colorScheme="teal">Button 2</Button>
        <Button colorScheme="teal">Button 3</Button>
      </Flex>
    </ChakraProvider>
  );
}

Spacer

The Spacer component is designed to be used alongside Flex. It creates a space as large as possible between two components. You can use it to create navbars like the one below. Notice how the Spacer is in between the two components where the space goes. This time, we are using a Flex with direction="column"

import { ChakraProvider, Flex, Button, Spacer, Heading } from '@chakra-ui/react'

export default function App() {
  return (
    <ChakraProvider>
      <Flex
        direction="row"
        width="full"
        align="center"
        gap="10px"
        padding="10px"
        bg="blue.100"
      >
        <Heading fontSize="sm">My app</Heading>
        <Spacer />
        <Button>Log in</Button>
        <Button colorScheme="teal">Sign up</Button>
      </Flex>
    </ChakraProvider>
  );
}

Practical Usage

Most apps can be made almost entirely using Flexes for layout. The most common layout in app design, is a vertical or horizontal layout. Most of the time, these layouts are nested. In a simple todo app, we would usually have a top level horizontal layout with both the sidebar and the main area, inside the sidebar a list of items (a vertical layout), and another vetical layout in the main area holding all the todos. Each todo itself is a horizontal layout.

Note that in the demo below, the checkboxes will not work as the done state is hardcoded. To get that to work, we need to modify the state whenever the checkbox changes.

import { ChakraProvider, Flex, Button, Spacer, Checkbox } from '@chakra-ui/react'

const todos = [
{
name: "Wash the cat",
done: true,
due: "Yesterday"
},
{
name: "Learn React",
done: false,
due: "Tomorrow"
},
{
name: "Sleep",
done: false,
due: "Eventually"
},
]

export default function App() {
  return (
    <ChakraProvider>
      <Flex direction="row" height="100vh">
        <Sidebar />
        <Todos />
      </Flex>
    </ChakraProvider>
  );
}

function Todo(props) {
return <Flex direction="row" gap="10px" bg="gray.400" rounded="md" gap="10px" padding="10px">

<Checkbox isChecked={props.done} />
{props.name}
<Spacer />
{props.due}

  </Flex>
}

function Todos() {
return <Flex direction="column" width="full" gap="10px" padding="10px">
{todos.map((todo) => <Todo {...todo} />)}

  </Flex>
}

function Sidebar() {
return <Flex direction="column" bg="gray.300" padding="20px" gap="20px">

<Button>A</Button>
<Button>B</Button>
<Button>C</Button>
</Flex>
}