Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Mixins that make it possible to use CSS Grid in IE 10/11 as well as in modern browsers. Based on mixins by Sascha Fuchs at https://medium.com/@gisugosu/css-grid-layout-spec-2-to-spec-1-transpiler-with-sass-415dff4dd31b.
/// Add Gap between the boxes
///
/// @author Sascha Fuchs
///
/// @group core - cssgrid
///
/// @param {list} $boxes - List with box sizes
/// @param {string} $gap - Optional column gap
@function box-gap($boxes, $gap) {
$box: ();
@for $i from 1 through length($boxes) {
$box: append($box, nth($boxes, $i), space);
// Adding Gap Between
@if $gap > 0 {
// Not last Loop
@if $i != length($boxes) {
$box: append($box, $gap, space);
}
}
}
@return $box;
}
/// To build Grid Template Columns with optional gap
///
/// @author Sascha Fuchs
///
/// @group core - cssgrid
///
/// @param {string} $gap - Optional column gap
/// @param {list} $columns - Columns sizes
///
/// @require {function} box-gap
///
/// @example scss - scss
/// .test {
/// @include grid-columns(10px 250px 1fr 50px 100px);
/// }
@mixin grid-columns($gap, $columns) {
grid-template-columns: $columns;
@if $gap > 0 {
grid-column-gap: $gap;
}
-ms-grid-columns: box-gap($columns, $gap);
}
/// To build Grid Template Rows with optional gap
///
/// @author Sascha Fuchs
///
/// @group core - cssgrid
///
/// @param {string} $gap - Optional row gap
/// @param {list} $rows - Rows sizes
///
/// @require {function} box-gap
///
/// @example scss - scss
/// .test {
/// @include grid-rows(10px 1fr);
/// }
@mixin grid-rows($gap, $rows) {
grid-template-rows: $rows;
@if $gap > 0 {
grid-row-gap: $gap;
}
-ms-grid-rows: box-gap($rows, $gap);
}
/// Generates IE10/11 grid placement to simulate grid-auto-flow.
///
/// @author Katherine Senzee
///
/// @param {map} $data - Information needed to tell IE exactly where to place everything.
/// @param {string} $data.autoflow - value for "grid-auto-flow". Either 'column' or 'row'.
/// @param {number} $data.columns - number of columns in the grid
/// @param {number} $data.rows - number of rows in the grid
/// @param {string} $data.gap - Where to allow for gaps. Should be 'column', 'row', or 'both'.
///
/// @example scss -
/// .quotes {
/// @include grid-autoflow(autoflow: column, columns: 3, rows: 6, gap: both);
/// }
@mixin grid-autoflow($data) {
$autoflow: map-get($data, autoflow);
$columns: map-get($data, columns);
$rows: map-get($data, rows);
$columnGap: false;
$rowGap: false;
@if (map-get($data, 'gap') == 'column') {
$columnGap: true;
$rowGap: false;
}
@else if (map-get($data, gap) == 'row') {
$columnGap: false;
$rowGap: true;
}
@else if (map-get($data, gap) == 'both') {
$columnGap: true;
$rowGap: true;
}
@else if (map-get($data, gap) == 'neither') {
$columnGap: false;
$rowGap: false;
}
@else {
@error The 'gap' argument must be one of 'column', 'row', 'both', or 'neither';
}
@if ($columnGap) {
$columns: $columns * 2 - 1;
}
@if ($rowGap) {
$rows: $rows * 2 - 1;
}
grid-auto-flow: $autoflow;
$column: 1;
$row: 1;
$counter: 1;
@if ($autoflow == 'column') {
@for $i from 1 through $columns {
@for $j from 1 through $rows {
// This element can be filled iff we are not in a row gap or a column gap.
@if ($i % 2 == 0 and $columnGap) {
// This is a column gap. Don't place the next element.
}
@else if ($j % 2 == 0 and $rowGap) {
// This is a row gap. Don't place the next element.
}
@else {
// Place the next element in column $i and row $j.
:nth-child(#{$counter}) {
-ms-grid-column: $i;
-ms-grid-row: $j;
}
$counter: $counter + 1;
}
}
}
}
@else if ($autoflow == 'row') {
@for $i from 1 through $rows {
@for $j from 1 through $columns {
// This element can be filled iff we are not in a row gap or a column gap.
@if ($i % 2 == 0 and $rowGap) {
// This is a row gap. Don't place the next element.
}
@else if ($j % 2 == 0 and $columnGap) {
// This is a column gap. Don't place the next element.
}
@else {
// Place the next element in row $i and column $j.
:nth-child(#{$counter}) {
-ms-grid-column: $j;
-ms-grid-row: $i;
}
$counter: $counter + 1;
}
}
}
}
}
// The CSS that's output will look something like this:
.my-class {
// Regular grid CSS for modern browsers.
display: grid;
grid-template-rows: auto auto;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 3em 1.5em;
grid-auto-flow: column;
// CSS for IE 10 and 11.
display: -ms-grid;
-ms-grid-columns: 1fr 1.5em 1fr 1.5em 1fr;
-ms-grid-rows: auto 3em auto;
}
// Because IE doesn't have the "grid-auto-flow" property, these declarations
// place each element in its grid cell, skipping cells that are only there
// to take the place of the column and row gaps that you define in modern
// browsers with the "grid-gap" property.
.my-class :nth-child(1) {
-ms-grid-column: 1;
-ms-grid-row: 1; }
.my-class :nth-child(2) {
-ms-grid-column: 1;
-ms-grid-row: 3; }
.my-class :nth-child(3) {
-ms-grid-column: 3;
-ms-grid-row: 1; }
.my-class :nth-child(4) {
-ms-grid-column: 3;
-ms-grid-row: 3; }
.my-class :nth-child(5) {
-ms-grid-column: 5;
-ms-grid-row: 1; }
.my-class :nth-child(6) {
-ms-grid-column: 5;
-ms-grid-row: 3; }
@import "grid_mixins";
// Usage example:
// This will create a 2-row, 3-column grid, with 1.5em gaps between
// the columns and 3em gaps between the rows.
.my-class {
display: grid;
display: -ms-grid;
@include grid-columns(1.5em, 1fr 1fr 1fr);
@include grid-rows(3em, auto auto);
@include grid-autoflow((autoflow: column, columns: 3, rows: 2, gap: both));
}
@markplewis

This comment has been minimized.

Copy link

@markplewis markplewis commented Jul 26, 2018

Thank you for posting these! In the grid-columns and grid-rows mixins, I changed @if $gap > 0 to @if $gap >= 0. Otherwise, if my element already had grid-row-gap: 10px;, then I'd be unable to override that value and change it to grid-row-gap: 0; via @include grid-rows(0, auto);. After modifying the mixins, I'm now able to do this. I'm also able to change grid-template-rows without affecting grid-row-gap via @include grid-rows(-1, auto);.

@theReal-Rob

This comment has been minimized.

Copy link

@theReal-Rob theReal-Rob commented Oct 19, 2018

This is awesome - thanks! I did notice one small issue, when using this the :nth-child was getting inherited to nested elements. A quick fix for that is to update line 141 & 162 from :nth-child(#{$counter}) to > :nth-child(#{$counter}) .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment