DEV Community

Victor Magarlamov
Victor Magarlamov

Posted on

6 1

Creating a flexbox-based Grid component in React

This post is about how to create a flexbox-based grid component in React. The component should be reusable, easy to configure, and allow us to make the following layouts:

---- ---- ---- ----
------ ------ ------
---------- ----------
---- ----------------
---- ----------- ----

Base React Componets

Let's create the components that we will work with.

const Grid = ({ children }) => (
  <div className='grid'>
    {children}
  </div>
);
const GridRow = ({ children }) => (
  <div className='grid__row'>
    {children}
  </div>
);
const GridColumn = ({ children }) => (
  <div className='grid__column'>
    {children}
  </div>
);

Now I append GridRow and GridColumn to the Grid component as static variables Grid.Row and Grid.Column.

import React from 'react';
import GridRow from './GridRow';
import GridColumn from './GridColumn';

const Grid = ({ children }) => (
  <div className='grid'>
    {children}
  </div>
);

Grid.Row = GridRow;
Grid.Column = GridColumn;

export default Grid;

Base styles

As already mentioned, the grid is based on flexbox, so we need to set the display property as 'flex'.

.grid, .grid__row {
  display: flex;
  width: 100%;
}

.grid {
  flex-direction: column;
  flex-wrap: nowrap;
}

.grid__row {
  flex-direction: row;
  flex-wrap: wrap;
}

Columns

In order to make a row with n-columns we need to set the width property of the columns. For example, if we want to get a 4-columns row, the value of the column width should be 25%, of 3 columns - 33%, of 2 columns - 50%. Therefore, we need CSS classes for these cases.

.grid__row--columns-4 > [class^="grid__column"] {
  width: 25%;
}

.grid__row--columns-3 > [class^="grid__column"] {
  width: 33%;
}

.grid__row--columns-2 > [class^="grid__column"] {
  width: 50%;
}

And let's modify the GridRow component.

import cx from 'classnames';

const GridRow = ({ children, columns = 4 }) => {
  const cls = cx('grid__row', {
    [`grid__row--columns-${columns}`]: columns,
  });

  return (
    <div className={cls}>
      {children}
    </div>
  );
};

And now we can do...

<Grid>
  <Grid.Row columns={4}>
    <Grid.Column>1</Grid.Column>
    <Grid.Column>2</Grid.Column>
    <Grid.Column>3</Grid.Column>
    <Grid.Column>4</Grid.Column>
  </Grid.Row>
</Grid>

---- ---- ---- ----

<Grid>
  <Grid.Row columns={3}>
    <Grid.Column>1</Grid.Column>
    <Grid.Column>2</Grid.Column>
    <Grid.Column>3</Grid.Column>
  </Grid.Row>
</Grid>

---- ---- ----

<Grid>
  <Grid.Row columns={2}>
    <Grid.Column>1</Grid.Column>
    <Grid.Column>2</Grid.Column>
  </Grid.Row>
</Grid>

---- ----

Columns with different widths

In order to make columns with different widths, we use the 'flex-grow' property.

.grid__column--width-3 {
  flex-grow: 3;
}

.grid__column--width-2 {
  flex-grow: 2;
}
const GridColumn = ({ children, width }) => {
  const cls = cx('grid__column', {
    [`grid__column--width-${width}`]: width,
  });
...

And now we can do such things:

<Grid>
  <Grid.Row columns={4}>
    <Grid.Column>1</Grid.Column>
    <Grid.Column width={2}>2</Grid.Column>
    <Grid.Column>3</Grid.Column>
  </Grid.Row>
</Grid>

---- ----------- ----

<Grid>
  <Grid.Row columns={3}>
    <Grid.Column>1</Grid.Column>
    <Grid.Column width={2}>2</Grid.Column>
  </Grid.Row>
</Grid>

---- ----------------

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay