Build Airbnb-style image cards with Chakra UI

Emadamerho-Atori Nefe

Card components are a way to group and display related information into a container. Sometimes users can interact with them by clicking or tapping to see more details.

In this article, we will learn how to build reusable, customizable, and responsive card component using Chakra UI.

Sandbox

The completed project is on CodeSandbox. Fork it and run the code.

The source code is also available on GitHub.

Prerequisites

The knowledge of Chakra UI is needed to get the most out of this article.

While we created the demo with Next.js, it is not a requirement, and we can transfer the knowledge to work with any frontend framework compatible with Chakra UI.

Getting Started

We create a Next.js project by running the command below in our terminal.

1npx create-next-app airbnb-cards-demo

Next, we navigate into the project directory.

1cd airbnb-cards-demo

We run the command below to install Chakra UI.

1npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6

Finally, we need to integrate Chakra UI into our application by adding ChakraProvider to the root of our application in the _app.js file.

pages/_app.js

1import { ChakraProvider } from '@chakra-ui/react'
2function MyApp({ Component, pageProps }) {
3 return (
4 <ChakraProvider>
5 <Component {...pageProps} />
6 </ChakraProvider>
7 )
8}
9export default MyApp

Creating the Custom Theme

Since we are modeling the cards after Airbnb, it is only proper we use the colors they used for their card component.

To do this, we create a theme/index.js file in the root directory and add the snippet below.

1import { extendTheme } from "@chakra-ui/react";
2
3const theme = extendTheme({
4 colors: {
5 black: "#000",
6 white: "#fff",
7 gray: {
8 50: "#717171",
9 100: "#222222",
10 },
11 },
12});
13
14export default theme;

We can extend Chakra UI’s default theme using the extendTheme function. We add white, black, and the shades of gray we need.

Creating the Card Component

An Airbnb card consists of the following:

  • an image of the property
  • the name of the property
  • the property’s distance
  • the property’s price
  • the date

We will need to create a card component that contains all of this information.

We begin by creating a components/Card.js file in the root and adding the code below:

1import { Box, Image, Heading, Text, Flex, Stack } from "@chakra-ui/react";
2
3export default function Card({ img, name, distance, date, price }) {
4 return (
5 <Box w="full">
6 <Image
7 h="337px"
8 w="full"
9 borderRadius="12px"
10 mb="10px"
11 src={`/images/${img}`}
12 alt="A house"
13 fontSize="16px"
14 objectFit="cover"
15 />
16 <Stack spacing="0">
17 <Flex justifyContent="space-between">
18 <Heading
19 as="h2"
20 fontWeight="bold"
21 color="gray.100"
22 fontSize="16px"
23 isTruncated
24 >
25 {name}
26 </Heading>
27 <Text as="span" color="gray.100" ml="4">
28 ${price}/night
29 </Text>
30 </Flex>
31 <Flex justifyContent="space-between">
32 <Text as="span" color="gray.50">
33 {distance} kilometers away
34 </Text>
35 <Text as="span" color="gray.50">
36 {date}
37 </Text>
38 </Flex>
39 </Stack>
40 </Box>
41 );
42}

In the code above:

  • We create the Card component. It accepts name, img, distance, date, and price through props.
  • The Image component takes in the img prop for the src. We set *objectFit* to cover to prevent the images from shrinking and getting distorted in reaction to the dimension of its parent.
  • We pass in the name, distance, date, price to their respective Chakra UI components.

The Properties’ Data

The code snippet below is a sample of the data we will pass to the card component through props.

1const data = [
2 {
3 name: "Lagos, Nigeria",
4 distance: "3,619",
5 date: "Mar 13 – 20",
6 price: "213",
7 img: "1.jpg",
8 },
9 {
10 name: "Delta, Nigeria",
11 distance: "3,619",
12 date: "Mar 13 – 20",
13 price: "213",
14 img: "2.jpg",
15 },
16 //more data objects below
17]

Setting up the Grid

Next, let’s set up the grid to lay out the cards.

To do that, we update the pages/index.js file with the code below:

1import Head from "next/head";
2import { Heading, SimpleGrid } from "@chakra-ui/react";
3import Card from "@components/Card";
4import data from "data/index";
5
6export default function Home() {
7 return (
8 <div>
9 <Head>
10 <title>Chakra UI Airbnb Card</title>
11 </Head>
12
13 <Heading as="h1" mb="10">
14 Chakra UI Airbnb
15 </Heading>
16
17 <SimpleGrid minChildWidth="300px" spacing="10" minH="full">
18 {data.map((house, i) => (
19 <Card
20 key={i}
21 name={house.name}
22 img={house.img}
23 distance={house.distance}
24 date={house.date}
25 price={house.price}
26 />
27 ))}
28 </SimpleGrid>
29 </div>
30 );
31}

In the code above, we use:

  • Head to add the metadata for the demo.
  • Heading to set the heading of the demo.
  • SimpleGrid to easily add a responsive grid layout for the cards. We iterate through the properties’ data and render the card for each property.

Creating the Layout Component

Finally, we need to give the demo a layout to bring it all together.

1import { Box } from "@chakra-ui/react";
2
3export default function Layout({ children }) {
4 return (
5 <Box maxW="1500px" p={["6"]} mx="auto" my="10">
6 {children}
7 </Box>
8 );
9}

We set the max-width of the app to 1500px and the horizontal margin to auto. By doing so, we vertically center the app.

Next, we use the layout in our pages/_app.js file by updating it with the code below:

1import { ChakraProvider, ScaleFade } from "@chakra-ui/react";
2import Layout from "@layout/index";
3import theme from "theme/index";
4
5function MyApp({ Component, pageProps, router }) {
6 return (
7 <ChakraProvider theme={theme}>
8 <Layout>
9 <ScaleFade key={router.route} initialScale={0.9} in="true">
10 <Component {...pageProps} />
11 </ScaleFade>
12 </Layout>
13 </ChakraProvider>
14 );
15}
16export default MyApp;

Besides adding the layout, we also use the ScaleFade component to add a nice transition to the demo.

The image below shows the completed demo.

Conclusion

Our components must not just be functional. They must also be responsive and pleasing to the eye. Chakra UI empowers us to create accessible, responsive, and appealing user interfaces.

This article taught us how to build a Grid of Airbnb-inspired cards using Chakra UI.

You may find these resources helpful:

Emadamerho-Atori Nefe

Frontend Developer and Technical Writer