Replicate Bootstrap 3 Grid Using CSS Grid

CSS Grid

Replicate Bootstrap 3 Grid Using CSS Grid

The past few years have seen a wide variety of methods for creating web page layouts. CSS Grid is one of the newest and most game-changing tools at our disposal. If you haven’t started tinkering with it yet, now is the time. It is a wildly different way of thinking about positioning content, and it currently has nearly full support across all common web browsers.

In order to replicate the majority of the features of the Bootstrap 3 grid system, we only require a small portion of the features that CSS Grid has to offer.

The key concept introduced in the Bootstrap 3 grid system which we will be replicating is the ability to explicitly define a grid container’s proportions for each responsive breakpoint. In comparison, Bootstrap 2 only defined the proportions for desktop, and any viewport smaller than 767px would render all grid items at full width, stacked vertically, in a single column.

1. Define our class names similar to those used in Bootstrap 3.

.row for a grid container

.col-[screenSize]-[numColumns] for a grid item where [screenSize] is one of our size abbreviations (xs,sm,md,lg,xl) and [numColumns] is a number from 1 to 12.

To use the CSS Grid, we simply apply display: grid; to our row class

.row {
  display: grid;

2. Define the number of columns in our grid and the size of the gutters (the space between items/columns).

Bootstrap uses 12 columns with 15px gutters.

  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-gap: 15px;

repeat(12, 1fr) is a shorthand for “1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1fr, 1fr” where ‘fr’ is a fractional unit. Setting all 12 of our columns to 1fr means they will all be the same width. By changing these values, we could easily create a grid with a different number of columns or with columns of varying widths.

3. Define the grid items that will go into it.

To do so we need only set the grid-column-end property for each variation of the grid item. Setting it to a value of ‘span 1’ would make the item one column wide. ‘Span 6’ would make it 6 columns wide, half of our 12 column grid.

There is much more that we could achieve with this property or with similar properties and shorthands for these properties. I encourage you to explore the possibilities and understand that we are only scratching the surface in this demo.

4. Fill out all the different span sizes at all the different breakpoints.

This is the most complex task we have to  The pattern is as follows:

@media (min-width: 0) {
  .col-xs-1 {
    grid-column-end: span 1;
  .col-xs-2 {
    grid-column-end: span 2;
  .col-xs-3 {
    grid-column-end: span 3;
  // ...up to .col-sm-12
@media (min-width: 768px) {
  .col-sm-1 {
    grid-column-end: span 1;
  .col-sm-2 {
    grid-column-end: span 2;
  .col-sm-3 {
    grid-column-end: span 3;
  //...up to .col-sm-12

…repeat for ‘md’ at 992px and ‘lg’ at 1200px

5. Build the pattern with a nested loop in Sass (once we understand the pattern) like so:

// Loop through responsive breakpoints
@each $size, $abbr in (0,xs),(768px,sm),(992px,md),(1200px,lg){
  @media (min-width: $size){
    // Loop through col classes
    @for $i from 1 through 12{
        grid-column-end: span $i;

6. Set a full width default for situations where the width is not defined.

For example, a grid item with the classes “col-md-4, col-sm-6” does not have a width defined when the viewport is smaller than 768px (the sm breakpoint).

However, it is defined for viewports larger than 992px (the md breakpoint) because the media query will continue applying the width for all viewports wider than 992px unless it is overridden by defining the lg width.

Rather than requiring devs to assign xs width for every item, we can safely make it full width as a default that the user can override if they choose to.

  grid-column-end: span 12;

This style rule will apply to any element with a class that begins with “col-” and set a 12 column width. The rule will be placed above our nested loop to ensure that the other grid styles override it.

See it in action. (Open in Codepen and change the viewer size)

[codepen_embed height=”265″ theme_id=”dark” slug_hash=”MpxQmW” default_tab=”css,result” user=”mobomo”]See the Pen Bootstrap 3 Grid with CSS Grid by Mobomo LLC (@mobomo) on CodePen.[/codepen_embed]


This implementation has several advantages over Bootstrap 3’s grid:

  1. All items in a row match the height of the tallest item
    • In Bootstrap 3, varying item heights would cause wrapping items to be improperly positioned, and it was a big headache.
  2. No need for element inside item to utilize gutter
    • Bootstrap 3’s gutter was applied to content within the item container not to the container itself. If you wanted a border or background color on the items to have the gutter space between them, you’d have to include another element within the grid item.
    • In CSS Grid, you can apply borders and backgrounds directly to the item and it will leave the gutter empty.
  3. No awkward rounded percentages
    • Bootstrap 3 relied on meticulously rounded percentages with repeating decimals.
    • CSS Grid uses explicitly defined fractions and does the math for us.
  4. No negative margin hacks
    • Bootstrap 3 gutters were carefully crafted with padding on each item and negative margins applied to the row to negate the padding on the first item of each row.
    • CSS Grid provides proper gutters out of the box.
  5. No clear-fix hacks
    • Bootstrap 3 grid items were floated left for wrapping and relied on the clearfix hack to push down content below.