Left and right arrow keys navigate. Enter jumps to content.

Change log

Please enable javascript to access the full functionality of this site

Site header

npm install gutter-grid --save

Tag line

A Sass flexbox based grid system that is able to replicate CSS grid-gap in IE11


Preferred system:

Version 7.0.0 - No more hidden overflow!

In Lu Nelson's comment on CSS Tricks, he suggested adding 0.01px of padding rather than using overflow: hidden or 1px of padding. The idea being that 0.01px of padding would get rounded down to 0px in browsers but it should still prevent margin collapse. I tried it out and 0.01px didn't work... but 0.1px did! 😁

Breaking changes

In version 7.0.0, I'm switching to using this 0.1px padding technique on the grid__wrapper element rather than using overflow: hidden. This means that grid__wrapper can now safely be used on elements that need overflow to be visible. This also means that the grid__paddedWrapper class that I added in version 4.1.0 has been made completely redundant.

grid__paddedWrapper hasn't been a part of Gutter Grid for very long so I'm outright removing it in this version. If you have used it in your codebase already and want to update to version 7.0.0, find and replace all instances of grid__paddedWrapper with grid__wrapper.

  • The grid__wrapper class now adds padding-bottom: 0.1px; rather than overflow: hidden;
  • The grid__paddedWrapper class has been removed from the class system.

New bogus CSS properties added

In this release I have added the following CSS properties to the Gutter Grid elements:

  • -gutter-grid-: grid;
  • -gutter-grid-: cell;
  • -gutter-grid-: inner;

They are meaningless to browsers but they are designed to make it easier for developers to spot elements that are using the Gutter Grid to form their layout.

One of the difficult parts of using the mixin version was trying to figure out what parts of the UI were using Gutter Grid and what parts weren't.

Adding these bogus CSS properties should make it easier to identify elements that are being affected by the Gutter Grid mixin.

I've added the properties to the class system as well. It is a little bit redundant but I think that having the bogus properties on the class system makes it more explicit where the styling is coming from.

Version 6.0.0 - Class System Bug Fix

I accidentally released a major bug in the Gutter Grid v5.0.0 class system. This release is only a bug fix but it will likely cause breakages in some peoples layouts so I'm playing it safe and releasing it as a new major version.

If you have version 5 and want to get the bug fix run this:

npm i gutter-grid@latest

Breaking change (the bug fix)

v5.0.0 was outputting this selector because I accidentally nested the selector inside the .grid__cell class.

.grid__cell .grid:not([class*="grid--cols"]):not(.grid--noStretch):not([class*="grid--align-"]):not([class*="grid--space-"]):not(.grid--noResize)
> .grid__cell:not(.grid__cell--noStretch):not(.grid__cell--noResize) {
  flex-grow: 1;

That means that the logic would only behave as intended if placed inside of a .grid__cell element. If placed outside of a .grid__cell element then the grid cells wouldn't grow.

My demos were all nested inside a grid cell so I didn't pick up on it until now.

This is what version 6.0.0 outputs:

> .grid__cell:not(.grid__cell--noStretch):not(.grid__cell--noResize) {
  flex-grow: 1;

Notice that there is no more .grid__cell class at the front.

Version 5.0.0 - Legacy mode fixes

This is a small release compared to version 4. It primarily sets out to fix some issues that version 4 had with IE 8 and 9 compatibility. It also brings legacy mode more into alignment with how modern mode behaves.

Breaking changes

  • Grids that have a set of columns defined would previously stretch while wrapping in legacy mode. This was inconsistent behavior to modern mode. In modern mode, grid cells would remain at their column width setting while wrapping. Legacy mode grids now behave consistently with modern mode grids with the exception of wrapping.
  • In general, legacy mode grids will not wrap unless explicitly told to. The exceptions to this rule are grids that have align, space, or vAlign settings applied to them and also grids that have had stretch disabled (grid--noStretch / $stretch: false and grid--noResize/$resize: false). vAlign, space and noStretch will automatically enable wrapping in legacy mode. vAlign will only enable wrapping in legacy mode if a column count has also been set. Previously these exceptions were not consistent in legacy mode between legacy and modern browsers. Using grid--noWrap/$wrap:false can overide this implicit wrapping behaviour to force modern browsers to not wrap. This technique will not prevent IE8 and 9 from wrapping though.

New features

  • You can now use $align: stretch or .grid--align-stretch to apply grid cell stretching instead of $stretch: true and the .grid--stretch class. Don't worry, you can still use $stretch: true and .grid--stretch, it's just an extra option you have available to you now.
  • Added legacy mode backups for vertical cell alignment. These backups will only come into effect though if wrapping is enabled and a column count has been defined.
  • Added a new grid--space-evenly class to the class system and $space: evenly setting to the mixin system. This is the equivalent of justify-content: space-evenly. It features a justify-content: space-around backup for browsers that don't support evenly yet and features an extra center alignment backup when running in legacy mode on browsers that don't support flexbox.

Version 4.1.0 - Mitigating the negative margin bug

This release is all about trying to mitigate the common negative margin browser bug as much as possible. Gutter Grid now tries it's best to avoid combining a negative top margin with a top gutter height. Instead Gutter Grid just doesn't output a top outer gutter unless the user has explicitly asked for one. If there is no outer gutter then there is no need to cancel it out with a negative margin which means no margin bug.

The bug is still an issue for bottom outer gutters though. The bottom negative margin cannot be removed. To combat this I've added a new class to the class system. The grid__paddedWrapper class adds padding-bottom: 1px instead of overflow: hidden. It is designed to be a replacement for the grid__wrapper class when overflow is needed. If using the mixin system padding-bottom: 1px needs to be added yourself to an element wrapping around the grid.

Version 4.0.0 - Making Gutter Grid more IE11 friendly

This is a big update. CSS Grid is killing off almost all need for Gutter Grid. IE 11 is essentially the only reason why Gutter Grid is still at all worth using right now. With IE 8 and 9 essentially dead, it doesn't make sense to hamper the experience of IE11 developers for the sake of these dead browsers. I'm optimising the code to make the experience as enjoyable as possible for IE11 devs. Unfortunately it means the defaults will be different depending on if $grid-legacy-support is enabled or not. If the legacy setting is turned on then Gutter Grid will behave in mostly the same way as it did in version 3.x.

Breaking changes:

Note: these breaking changes mostly apply only when the $grid-legacy-support is set to false (the default setting).

  • New default settings
    • $align in the mixin now defaults to left.
    • $wrap in the mixin now defaults to true but only if $cols has been defined.
    • Grids no longer stretch by default. In order to make the grid stretch like it did in v3.x, if using the classes system, a grid--stretch class needs to be added to the .grid element. If using the mixin system, a $stretch: true setting needs to be called in the mixin. This is only necessary if columns have been defined.
    • Grids with a column count setting will now wrap by default unless if wrapping is explicitly disabled or $grid-legacy-support is enabled.
  • The grid--noGrowth class has been renamed grid--noStretch to align with the new grid--stretch class. (A breaking change for everyone).
  • The $grow setting in the mixin has been renamed to $stretch. (A breaking change for everyone).
  • Multi-spanning cells now flex-grow by default. (A breaking change for everyone).
  • $breakpoints parameter in the mixin has been moved to the 3rd slot. (A breaking change for everyone).
  • $grid-break-points setting now has new syntax that makes it easier to tell what column count a particular set of breakpoints is for. Below is an impracticle example showing the new format:

    Version 3.x
    $grid-break-points: (
      // No media queries for 1 column grid
      // 2 column grid breakpoints
        // At 600px wide screen and below, make columns 100% wide
        100%: 600px,
      // No media queries for 3 column grid
      // 4 column grid breakpoints
        50% : 960px,
        100% : 600px,
      // No media queries for a 5 column grid
    Version 4.0.0
    $grid-break-points: (
      // No need to mention a 1 column grid
      // 2 column grid breakpoints
      2: (
        // At 600px wide screen and below, make it a 1 column grid
        // (using percentages here instead of column count still works)
        1: 600px,
      // No need to mention a 3 column grid
      // 4 column grid breakpoints
      4: (
        2 : 960px,
        1 : 600px,
      // No media queries for 5 column grid
      // Only needed if using the class system
      5: false,

New features:

  • Instead of listing percentage values as keys in the $breakpoints parameter key/value pairs, you can now simply list the number of columns that the grid should have as the keys in the key/value pairs. The old method of using percentages as the key values will still work if that method is preferred.

    Version 3.x (Still works in version 4)
    @include grid(7, $breakpoints: (
      // On a 960px wide screen or below, the columns will be 25% wide
      25% : 960px,
      // You can use mq-scss syntax here as well
      50% : (max, 600px),
      100% : 480px,
    Version 4.0.0
    @include grid(7, $breakpoints: (
      //On a 960px wide screen or below, there will be 4 columns
      4 : 960px,
      // You can still use mq-scss syntax here as well
      2 : (max, 600px),
      1 : 480px,
  • calc is now used by default to determine column widths. So instead of seeing width: 33.33%; in your styles, you will see width: calc(100% / 3);. This makes it clear from the styles how many columns are being generated. For example it is much clearer that width: calc(100% / 7); equals 7 columns rather than width: 14.2857%;.

  • New config variable $grid-calc-support has been introduced. Since calc isn't supported in every browser (thanks Opera Mini and Android 4) a new $grid-calc-support setting has been added. This defaults to whatever the opposite of the $grid-legacy-support setting is. This means that if legacy support is needed then $grid-calc-support will automatically be disabled. If you need to support Opera Mini (or you prefer seeing percentages in your styles), set $grid-calc-support to false.

Version 3.0.0 - Upgrading mq-scss and legacy support is no longer the default

  • Gutter Grid will now install whatever version of mq-scss is available (defaulting to the latest version)
  • Breaking change: You now need to set the $grid-legacy-support setting to true if you wish to support browsers that do not support flexbox natively. (Change made to drastically reduce the amount of bloat found in the output css).

Version 2.0.0 - Gutter Grid now in mixin flavor!

What's new?

  • Gutter Grid now comes in mixin flavour!
  • Gutters can now have different vertical vs horizontal gutter widths
  • Column media queries can now take mq-scss syntax for defining completely custom breakpoints
  • Improved legacy browser support
  • Reduced specificity on class based selectors for easier overriding of styles

Breaking changes

Reduced specificity in class names

If upgrading, none of the class names have changed, however the reduced specificity will mean that you may need to update your styles to not conflict with the new grid system.

New format for assigning column break points

The new format to the column break points is a bit different to the original. before it was a list of screen-sizes then column widths with a space in between each one.

Version 1.x
  600px 100%

Column width is now stated first, and screen width is stated second. By default, the screen width will be calculated as a max-width media query. However, you can now provide mq-scss syntax as an alternative to stating a screen width pixel value. This means that you can define the column break points using just about any media query you like. Taking a mobile first min-width approach will break legacy browser support though unless you have UnMQ integrated into your build process.

Version 2.x
  100% : 600px, //state a max-width pixel value
  100% : (max, 600px), //provide a custom mq-scss media query
New format for assigning gutter break-points

The new way of assigning breakpoints to gutters isn't much different to the original method. The only incompatible difference being that now you need to write mq with a space after it before the list of values (the space is vital).

Version 1.x
$grid-cell-gutters: (
    'mediaQueryGutter' : (
        30px (max, 800px),
        10px (max, 700px)
Version 2.x
$grid-cell-gutters: (
    'mediaQueryGutter' : mq (
        30px (max, 800px),
        10px (max, 700px)