CSS Grid: First Steps

March 2, 2017

I am excited about the new layout tools available to solve front-end development problems. I started utilizing Flexbox on almost every project last year. And recently I added CSS Grid Layout to my toolbox.

Reading, Watching Videos, and Experimenting

I took some time off in December because I needed a break from everyday project work. But one of the things that energized me was taking a couple of days to dive into CSS Grid. I had bought Rachel Andrew’s book, Get Ready for CSS Grid Layout when it came out last January but had not read through it yet. I was motivated by the news that the CSS Grid Specification was going to start showing up in browsers this spring.

I was able to consume Rachel’s book over a course of two days as I took some time to play around in CodePen to apply what I was reading. Nothing beats learning by doing. After finishing her ebook, I watched videos on Grid by Example. I followed along with her Start Learning Grid Layout daily series on the site’s blog. In just a couple of days, I felt very equipped to start experimenting with CSS Grid.

Thanks to Jen Simmons, I also learned of an approach to start incorporating CSS Grid into my work right away. Jen wrote an article about Feature Queries which allows us to target modern browsers that support certain features and write CSS for those browsers while depending on fallbacks for other browsers (progressive enhancement).

Finding Connections with What I Already Knew

One advantage I had in learning Grid Layout is that I had started my career building table-based layouts. There are a lot of similar concepts in CSS Grid Layout to the ways I had to think about putting together a site build using tables. Another advantage I had is that I had studied grids as a layout method back when I was both designing and building out sites.

I confess that CSS Grid looked a bit daunting. Just looking at the code in CSS, it seemed really difficult to wrap your head around it. But Rachel’s videos and examples really helped me to feel less intimidated. As the video series progressed, I got more comfortable with the syntax. So much so that I started thinking about how CSS Grid could solve a common front-end pattern that I have encountered in every recent project.

Test Drive with a Common Front-end Pattern

The common pattern that I encountered is a listing for articles, products or projects that includes a thumbnail image, article title/product or project name, and possibly a short description. The layout that the designer chose as his or her solution is a grid usually ending in a three, four, or five column grid with multiple rows. Just the sort of layout that CSS Grid Layout was created to solve.

CSS Grid provides a much more streamlined and elegant solution to the problem then the methods we have been using to implement this pattern. My tool of choice has been floats. But in a responsive design, they can get really messy as the viewport becomes wider giving us the space to move from a one column linear layout to multiple columns.

Here is an example of what CSS might look like for that using floats. Note: Susan Robertson shared a similar example a couple of weeks ago.

// Clearfix solution to clear the floats
.listing-container::after {
  content:'';
  display: table;
  clear: both;
}

.list-item {
  width:100%;	
}
.list-item:not(:first-child) {
  margin-top:1em;
}

// Two Columns

@media screen and (min-width:30em) {
  .list-item {
    float:left;
    width:49%;
  }	

  .list-item:nth-child(2n+1) {
    clear:left;
    margin-right:2%;
  }

  .list-item:nth-child(2) {
    margin-top:0;
  }

}

//Three Columns

@media screen and (min-width:37.5em) {
  .list-item {
    width:32%;
  }	

  .list-item:nth-child(2n+1) {
    clear:none;
    margin-right:0;
  }

  .list-item:nth-child(3n+1) {
    clear:left;
  }

  .list-item:not(:nth-child(3n+1)) {
    margin-left:1.5%;
  }

  .list-item:nth-child(3) {
    margin-top:0;
  }

}

// Four Columns

@media screen and (min-width:60em) {
  .list-item {
    width:24%;
  }	

  .list-item:nth-child(3n+1) {
    clear:none;
  }

  .list-item:not(:nth-child(3n+1)) {
    margin-left:0;
  }

  .list-item:nth-child(4n+1) {
    clear:left;
  }

  .list-item:not(:nth-child(4n+1)) {
    margin-left:calc(4% / 3);
  }

  .list-item:nth-child(4) {
    margin-top:0;
  }
	
}

Note: I have not used prefixes in my CSS so that I could keep my examples simple. I use autoprefixer and let my build tool add the appropriate prefixes.

I have to write several lines of code for each breakpoint just to reset items that clear the float and to reset horizontal margins between the list items.

Now observe how much cleaner and less code I have to write with CSS Grid Layout:

.listing-container {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  grid-row-gap:1em;
}

// Two Columns

@media screen and (min-width:30em) {
  .listing-container {
    grid-template-columns: repeat(2, 1fr);	
    grid-column-gap:1em;
  }
}

//Three Columns

@media screen and (min-width:37.5em) {
  .listing-container {
    grid-template-columns: repeat(3, 1fr);	
  }	
}

//Four Columns

@media screen and (min-width:37.5em) {
  .listing-container {
    grid-template-columns: repeat(4, 1fr);	
  }	
}

This is a simple example where I am keeping the margin between rows the same and the margin between the list items the same through the different breakpoints. But I could easily change those values at each breakpoint with a one-line declaration.

I have also simplified my code above just to show the difference on how much CSS it takes to change the layout. Using Grid Layout today, I would use a the float solution as my baseline and then put my Grid Layout declarations in a feature query along with some declarations to override the floats.

To simplify my CSS, I am using !important so I only have to clear the float declarations once. (As a rule, I try to avoid using !important in my CSS and only use it when I know there will not be a conflict down the cascade which would need another !important declaration.)

@supports (display:grid) {

  .listing-container {
    display: grid;
    grid-template-columns: repeat(1, 1fr);
    grid-row-gap:1em;
  }

  .listing-container:after {
    display: none;	
  }

// Two Columns

  @media screen and (min-width:30em) {
    .listing-container {
      grid-template-columns: repeat(2, 1fr);	
      grid-column-gap:1em;
    }

    .list-item {
      clear:none !important;	
      float:none !important;	
      margin:0 !important;
      width:auto !important;
    }
  }

//Three Columns

  @media screen and (min-width:37.5em) {
    .listing-container {
      grid-template-columns: repeat(3, 1fr);	
    }	
  }

//Four Columns

  @media screen and (min-width:37.5em) {
    .listing-container {
      grid-template-columns: repeat(4, 1fr);	
    }	
  }

}

See simple example of this pattern on CodePen

Next Steps

I am really excited about CSS Grid Layout. I look forward to continued to experimentation. And with feature queries, I intend to integrate it into my upcoming projects. I plan to continue to write about what I learn and post links to resources that I find helpful.

Resources


2 Comments

  1. Stephen Ainsworth

    March 8th, 2017

    I also found myself approaching CSS Grid Layout the same as I did with tables. I used to sketch the design of an email template on a piece of paper to deconstruct how I was going to build it in tables, and found myself doing the same with CSS Grid Layout.

  2. Chris

    March 10th, 2017

    Thank you for incorporating those resources you provided. Quite helpful.