Aysha Anggraini

On code, design, and movement

CSS Grid for the Traditionalists

CSS Grid opens a plethora of new possibilities for designing layouts. We can finally let go of the 12-columns layout since our new tools made it easier to manipulate our grid system. However, I still believe that 12-columns layout is still going to be a thing at least until the adoption of CSS Grid becomes more common. A wider adoption of CSS Grid means more sites with unique layouts and that means more source materials for designers to take inspiration from.

Despite the hype surrounding CSS Grid, there are developers who are still reluctant to embrace it. Some cites browser support as a reason; others would probably need to wrestle with some complicated requirements. For me, even though I jumped right in to experiment with it, I didn’t find a strong pull to start using CSS Grid in production because I already have a traditional percentage-based grid system written with floats. Also, I am still stuck with the traditional 12-columns layout design. So I didn’t think it was worth it.

If you have the same thoughts as I did and have yet to explore CSS Grid, I believe one of the best ways for you to start using CSS Grid is by converting your traditional grid system to CSS Grid. Don’t let browser supports stop you; at the time of writing, Can I Use shows a global availability of 86.59%. Even if you are supporting old browsers, @supports statement can help with that so that you can write fallback layouts using flexbox, floats, etc.

Mark-up First

I believe you should always write your mark-up first before you start writing any CSS just to make sure your structure of content is correct and that you are not prioritising your styling over content structure. When you are transforming an existing grid system to CSS Grid, sticking to your current content structure is crucial. Obviously, you do not want to change each and every structure and class names in your HTML. A typical float-based grid system would have a mark-up that looks like this:

<div class="row">
  <div class="col s12">
    s12 (12-columns wide on all screen sizes)
  </div>
  <div class="col s6">
    s6 (one-half on all screen sizes)
  </div>
  <div class="col s6">
    s6 (one-half on all screen sizes)
  </div>
</div>

Studying your current mark-up first will help you write CSS in a way that ensures you are retaining the content structure as closely as possible. But you may have the intention of displaying the order of your content differently.

With CSS Grid, it is possible to display your content structure in different order by using the order property. Keep in mind that screen readers and keyboard navigation will follow the content structure that is defined in the HTML docs instead of how they are displayed on the screen. So, it is important to think about your content structure deeply from the get-go.

CSS Grid with Feature Queries

The next part involves overriding your traditional grid system by using @supports statement (feature queries). It is best to understand how CSS Grid overrides will affect your current solution. This fallbacks and overrides cheat sheet by Rachel Andrew is a good guide that you can refer to. Depending on your initial solutions (flex, floats, inline blocks, etc.), you may want to find out how CSS Grid overrides can affect the behaviour of your chosen initial solution.

In my case, I used a percentage-based grid system with floats. The initial version of my CSS looks like this (I am using SCSS):

$num-cols: 12;
$spacing-width: 8px;

// mixins for generating percentage based columns
@mixin columns-generator($class-name) {
  $i: 1;
  @while $i <= $num-cols {
    $perc: unquote((100 / ($num-cols / $i)) + "%");
    
    .#{$class-name}#{$i} {
      width: $perc;
    }
    
    $i: $i + 1;
  }
}

.row {
  margin-left: -($spacing-width);
  margin-right: -($spacing-width);
  
  &:after {
    content: "";
    display: table;
    clear: both;
  }

  .col {
    box-sizing: border-box;
    float: left;
    padding: 0 $spacing-width;
  }
}

@include columns-generator("small-");

@media (min-width: 53em) {
  @include columns-generator("med-");
}

@media (min-width: 75em) {
  @include columns-generator("large-");
}

Then, I add CSS Grid using feature queries and override the fallback layout:

$spacing-width: 8px;

// mixin for generating CSS grid column
@mixin grid-columns-generator($class-name) {
  $i: 1;
  @while $i <= $num-cols {
    .#{$class-name}#{$i} {
      grid-column: span $i;
    }

    $i: $i + 1;
  }
}

// For browsers that supports grid, reset all the values above
@supports(display: grid) {
  .row {
    margin-left: auto;
    margin-right: auto;
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-gap: $spacing-width * 2;

    &:after {
      content: none;
    }
  }
  
  .grid-bg {
    margin: auto;
  }

  .row > * {
    width: auto;
  }

  .row .col {
    width: auto;
    padding: 0;
  }

  @include grid-columns-generator("small-");

  @media (min-width: 53em) {
    @include grid-columns-generator("med-");
  }

  @media (min-width: 75em) {
    @include grid-columns-generator("large-");
  }
}

The entire finish product can be viewed in the pen here:

But Beware…

When you are developing solely on a modern browser that supports CSS Grid, it is easy to get carried away and not check how your fallback layout is faring with each and every element you add or structures that you have changed. If you are using floats as a fallback layout, there are some behaviour that you need to watch out for.

For example, lets say that you have a markup that looks like this:

<div class="row">
  <div class="col small-12 med-6">
    <div class="grid-bg center">
      <strong>The Header</strong> (span the entire 12 columns on small screen size and 6 columns on medium to large device)
    </div>
  </div>
  <div class="col small-12 med-6">
    <div class="grid-bg"><strong>Content</strong>
    </div>
  </div>
  <div class="col small-12 med-6">
    <div class="grid-bg"><strong>Sidebar</strong> </div>
  </div>
</div>

With CSS Grid, the layout looks correct. All of the boxes were positioned as expected:

But for browsers that do not support CSS Grid, our float layout will be rendered instead and this is how it looks like:

It is easy to get carried away and not realise that our mark-up structure may work well with CSS Grid but not with our fallback layout. Therefore, it is important to keep on testing and ensure that the site is still readable and the layout structure is not too disjointed on non-supporting browsers.

The Beauty of Progressive Enhancement

Feature queries is an example of progressive enhancement. Render a simple layout design on older browsers but enhance it with new CSS feature for modern browsers. Progressive enhancement means that layouts do not need to look the same on all browsers. It is okay to have a minimalistic layout design on older browsers and an improved version on modern ones. That being said, I believe it is important to ensure that the layout and content should still look decent and readable on older browsers so that such browser users do not have a disjointed experience.

Final Thoughts

I’ve created some experiments with CSS Grid before but I only realise how much I appreciate CSS Grid once I start using it in production. I appreciate how it makes building layout much simpler. When I see a layout design that looks quite experimental, I can quickly visualise how I am going to turn that design into code. I am no longer limited by the older layout tools in CSS. There’s a new standard in town and I happily embrace it.

I know that the examples that I show in this post is quite simple but I hope it helps someone out there who wants to start working with CSS Grid in their production code. I believe once you start understanding CSS Grid, you wouldn’t want to use any other layout methods if you can help it!