How to create a better React grid layout component

For a while, I automatically added some CSS framework to add a grid layout system. I came to realize why add another dependency? Can I just create a simple grid React component that I can add to my project?

The answer is, yes. With the CSS flex capabilities, making layouts is really easy. Combined CSS flex with React, and you got yourself a pretty powerful grid tooling system.

Try to avoid installing third party libraries for a grid layout component. Avoid the extra dependency and load.

Click here if you want to go to the Github source code.

Otherwise let’s get started!

Grid layout component CSS

This layout breaks it into a 12 column grid layout by using a row and column grid style layout.

Most bootstraps follow this convention.


.row {
  display: flex;
  flex-flow: row wrap;
  max-width: 75rem;
  margin-right: auto;
  margin-left: auto;
}

.row.expanded {
  max-width: none;
}

.flex-start {
  justify-content: flex-start;
}

.center {
  justify-content: center;
}

.flex-end {
  justify-content: flex-end;
}

.space-between {
  justify-content: space-between;
}

.space-around {
  justify-content: space-around;
}

.space-evenly {
  justify-content: space-evenly;
}

.align-center {
  align-items: center;
}

.column {
  flex: 1 1 0px;
  padding-left: 0.9375rem;
  padding-right: 0.9375rem;
  box-sizing: border-box;
}

.column > .row {
  margin-left: -0.9375rem;
  margin-right: -0.9375rem;
}

.sm-1 {
  flex: 0 0 8.33333%;
  max-width: 8.33333%;
}

.sm-2 {
  flex: 0 0 16.66667%;
  max-width: 16.66667%;
}

.sm-3 {
  flex: 0 0 25%;
  max-width: 25%;
}

.sm-4 {
  flex: 0 0 33.33333%;
  max-width: 33.33333%;
}

.sm-5 {
  flex: 0 0 41.66667%;
  max-width: 41.66667%;
}

.sm-6 {
  flex: 0 0 50%;
  max-width: 50%;
}

.sm-7 {
  flex: 0 0 58.33333%;
  max-width: 58.33333%;
}

.sm-8 {
  flex: 0 0 66.66667%;
  max-width: 66.66667%;
}

.sm-9 {
  flex: 0 0 75%;
  max-width: 75%;
}

.sm-10 {
  flex: 0 0 83.33333%;
  max-width: 83.33333%;
}

.sm-11 {
  flex: 0 0 91.66667%;
  max-width: 91.66667%;
}

.sm-12 {
  flex: 0 0 100%;
  max-width: 100%;
}

@media screen and (min-width: 40em) {
  .md-1 {
    flex: 0 0 8.33333%;
    max-width: 8.33333%;
  }

  .md-2 {
    flex: 0 0 16.66667%;
    max-width: 16.66667%;
  }

  .md-3 {
    flex: 0 0 25%;
    max-width: 25%;
  }

  .md-4 {
    flex: 0 0 33.33333%;
    max-width: 33.33333%;
  }

  .md-5 {
    flex: 0 0 41.66667%;
    max-width: 41.66667%;
  }

  .md-6 {
    flex: 0 0 50%;
    max-width: 50%;
  }

  .md-7 {
    flex: 0 0 58.33333%;
    max-width: 58.33333%;
  }

  .md-8 {
    flex: 0 0 66.66667%;
    max-width: 66.66667%;
  }

  .md-9 {
    flex: 0 0 75%;
    max-width: 75%;
  }

  .md-10 {
    flex: 0 0 83.33333%;
    max-width: 83.33333%;
  }

  .md-11 {
    flex: 0 0 91.66667%;
    max-width: 91.66667%;
  }

  .md-12 {
    flex: 0 0 100%;
    max-width: 100%;
  }
}

@media screen and (min-width: 64em) {
  .lg-1 {
    flex: 0 0 8.33333%;
    max-width: 8.33333%;
  }

  .lg-2 {
    flex: 0 0 16.66667%;
    max-width: 16.66667%;
  }

  .lg-3 {
    flex: 0 0 25%;
    max-width: 25%;
  }

  .lg-4 {
    flex: 0 0 33.33333%;
    max-width: 33.33333%;
  }

  .lg-5 {
    flex: 0 0 41.66667%;
    max-width: 41.66667%;
  }

  .lg-6 {
    flex: 0 0 50%;
    max-width: 50%;
  }

  .lg-7 {
    flex: 0 0 58.33333%;
    max-width: 58.33333%;
  }

  .lg-8 {
    flex: 0 0 66.66667%;
    max-width: 66.66667%;
  }

  .lg-9 {
    flex: 0 0 75%;
    max-width: 75%;
  }

  .lg-10 {
    flex: 0 0 83.33333%;
    max-width: 83.33333%;
  }

  .lg-11 {
    flex: 0 0 91.66667%;
    max-width: 91.66667%;
  }

  .lg-12 {
    flex: 0 0 100%;
    max-width: 100%;
  }
}

The CSS also uses 3 breakpoints for mobile, tablet, and desktop viewports:

  • Mobile viewport: < 40em
  • Tablet viewport: >= 40em
  • Desktop viewport: >= 64em

Creating the grid layout component

I’m going to create a file called Grid.jsx in my components directory.


const Grid = props => {
  const {
    alignItems,
    children,
    column,
    expanded,
    justify,
    lg,
    md,
    row,
    sm
  } = props;

  const isRow = row || !column;

  const classes =
    (!isRow ? styles.column : styles.row) +
    // Row styling
    (isRow && expanded ? ` ${styles.expanded}` : "") +
    (isRow && justify ? ` ${styles[justify]}` : "") +
    (isRow && alignItems ? ` ${styles["align-" + alignItems]}` : "") +
    // Column styling
    (!isRow && sm ? ` ${styles["sm-" + sm]}` : "") +
    (!isRow && md ? ` ${styles["md-" + md]}` : "") +
    (!isRow && lg ? ` ${styles["lg-" + lg]}` : "");

  return <div className={classes}>{children}</div>;
};

export default Grid;

The Grid components accepts a handful of properties. Let’s go over each one of them.

row – Lets the component know this is going to be a row. This the default value.

column – Converts the component from a row to a column. This is useful to add inside your row component.

expanded – This is property is for Grid components that are rows. It gives the row full width of the parent element.

alignItems – Defines the CSS property align-items. This property works with the row type component.

justify – Defines the CSS property justify-content. This property works with the row type component.

sm – Defines the size of the column from mobile to desktop; if not overriden.

md – Defines the size of the column for tablet viewport and wider; if not overriden.

lg – Defines the size of the column for desktop viewport and wider; if not overriden.

Creating a grid layout component with TypeScript

If you’re like me, who develops React with TypeScript. Here’s a TypeScript version of the Grid component.

First take the file Grid.jsx and rename it to Grid.tsx.

Here’s a command version if you’re a pro!


mv ./components/Grid.jsx ./components/Grid.tsx

There’s a couple changes we need to make to the file. One being that we need to add our types and interfaces that defines how this React component is made up.


type GridItemsAlignment =
  | "flex-start"
  | "center"
  | "flex-end"
  | "stretch"
  | "baseline";

type GridJustify =
  | "flex-start"
  | "center"
  | "flex-end"
  | "space-between"
  | "space-around"
  | "space-evenly";

type GridSizes = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;

interface GridProps {
  alignItems?: GridItemsAlignment;
  column?: boolean;
  expanded?: boolean;
  justify?: GridJustify;
  lg?: GridSizes;
  md?: GridSizes;
  row?: boolean;
  sm?: GridSizes;
}

I’ve create an interface called GridProps that is the definition of the Grid component.

now I must attach the GridProps interface to the Grid function or class component.


// React functional component
const Grid: React.SFC<GridProps> = props => {}

// React class component
class Grid extends React.Component<GridProps> {}

Here’s my full code of the Grid component written in TypeScript.


import * as React from "react";

import styles from "./Grid.module.css";

type GridItemsAlignment =
  | "flex-start"
  | "center"
  | "flex-end"
  | "stretch"
  | "baseline";

type GridJustify =
  | "flex-start"
  | "center"
  | "flex-end"
  | "space-between"
  | "space-around"
  | "space-evenly";

type GridSizes = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;

interface GridProps {
  alignItems?: GridItemsAlignment;
  column?: boolean;
  expanded?: boolean;
  justify?: GridJustify;
  lg?: GridSizes;
  md?: GridSizes;
  row?: boolean;
  sm?: GridSizes;
}

const Grid: React.SFC<GridProps> = props => {
  const {
    alignItems,
    children,
    column,
    expanded,
    justify,
    lg,
    md,
    row,
    sm
  } = props;

  const isRow: boolean = row || !column;

  const classes: string =
    (!isRow ? styles.column : styles.row) +
    // Row styling
    (isRow && expanded ? ` ${styles.expanded}` : "") +
    (isRow && justify ? ` ${styles[justify]}` : "") +
    (isRow && alignItems ? ` ${styles["align-" + alignItems]}` : "") +
    // Column styling
    (!isRow && sm ? ` ${styles["sm-" + sm]}` : "") +
    (!isRow && md ? ` ${styles["md-" + md]}` : "") +
    (!isRow && lg ? ` ${styles["lg-" + lg]}` : "");

  return <div className={classes}>{children}</div>;
};

export default Grid;

How to use the Grid layout component

The hard part is done. Building grid layouts will be simple.

This will remove the repetitiveness of styling for layouts on every other React component, and installing third party libraries that are just not needed.

Here’s an example how to use it.


import Grid from "./components/Grid";

const App = () => {
  return (
    <Grid row={true}>
      <Grid column={true} sm={12} md={4}>
        <h1>Column 1</h1>
      </Grid>
      <Grid column={true} sm={12} md={4}>
        <h1>Column 2</h1>
      </Grid>
      <Grid column={true} sm={12} md={4}>
        <h1>Column 3</h1>
      </Grid>
    </Grid>
  );
};

There you go, you don’t need to install a third part library for grid layouts anymore.

Github source code example

Click here to go to Ruben’s React Grid component Github code example.

Oh wow, you’ve made it this far! If you enjoyed this article perhaps like or retweet the thread on Twitter:

I like to tweet about React and post helpful code snippets. Follow me there if you would like some too!