DEV Community

Victor Magarlamov
Victor Magarlamov

Posted on

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>

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

Top comments (0)