CSS Grid in IE: Duplicate area names now supported!

Autoprefixer is now up to version 9.3.1 and there have been a lot of updates since I wrote the original three-part CSS Grid in IE series — the most important update of which is the new grid-areas system. This is mostly thanks to Bogdan Dolin, who has been working like crazy to fix loads of Autoprefixer issues. Autoprefixer’s grid translations were powerful before, but they have gotten far more powerful now!

Article Series:

  1. Debunking common IE Grid misconceptions
  2. CSS Grid and the new Autoprefixer
  3. Faking an auto-placement grid with gaps
  4. Duplicate area names now supported! (This Post)

How Autoprefixer supports duplicate area names

In Part 2 of the series, I pointed out why Autoprefixer wasn’t able to handle duplicate area names that were used across multiple selectors.

To summarize, this is the example I gave in the article:

.grid-alpha { grid-template-areas: "delta echo";
} .grid-beta { grid-template-areas: "echo delta";
} .grid-cell { /* What column does .grid-cell go in? */ -ms-grid-column: ???; grid-area: echo;
}

We thought that since Autoprefixer didn’t have access to the DOM, there was no way of knowing what grid the grid cell belonged to and thus which column the grid cell should go in.

However, I realized something. Grid cells are only ever affected by their direct parent element (ignoring display: contents). That meant that if the grid cell exists, it will always be a direct child of the grid template element. This gave me an idea for how we can solve the grid-area name conflict! 😁

.grid-alpha { grid-template-areas: "delta echo";
} .grid-beta { /* Uh oh, duplicate area names! */ grid-template-areas: "echo delta";
} .grid-cell { /* We will use the first occurrence by default */ -ms-grid-column: 2; grid-area: echo;
} /* We have detected a conflict! Prefix the class with the parent selector.
*/
.grid-beta > .grid-cell { /* NO MORE CONFLICT! */ -ms-grid-column: 1;
}

The entire grid-areas system needed to be re-written to achieve this, but it was totally worth the effort.

The way this new system works is that .grid-cell will default to using the first grid-template-areas property that it comes across. When it hits a conflicting grid template, it will create a new rule placing the parent selector in front of the child selector like so:

[full parent selector] > [direct child selector]

This is what we know purely from looking at the CSS and knowing how CSS Grid works:

  • A grid cell must be a direct descendant of the parent grid container for CSS Grid to work (assuming display: contents isn’t used).
  • grid-beta > .grid-cell will only work on .grid-cell elements that have been placed directly inside a .grid-beta element.
  • .grid-beta > .grid-cell will have no effect on .grid-cell elements placed directly inside .grid-alpha elements.
  • .grid-beta > .grid-cell will have no effect on .grid-cell elements nested deeply inside .grid-beta elements.
  • .grid-beta > .grid-cell will override the styling of the lonely .grid-cell CSS rule both because of rule order and specificity.

Because of those reasons, Autoprefixer can pretty safely resolve these conflicts without having any access to the DOM.

That last point in the list can be a little bit dangerous. It increases specificity which means that it may cause some IE styles to override others in a way that is different from how modern overrides are working. Since the generated rules only hold IE-specific grid styles, and they only apply under very specific circumstances, this is unlikely to cause an issue in 99.999% of circumstances. There is still potential for edge cases though.

If you ever find yourself needing to increase the specificity of the grid cell selector, here’s how to go about it.

Instead of writing this:

.grid { grid-template-areas: "area-name";
} .grid-cell { grid-area: area-name;
}

…we write the rule like this:

.grid { grid-template-areas: "area-name";
} .grid > .grid-cell { grid-area: area-name;
}

Autoprefixer will retain the selector and output something like this:

.grid { grid-template-areas: "area-name";
} .grid > .grid-cell { -ms-grid-column: 1; -ms-grid-row: 1; grid-area: area-name;
}

The exciting new possibilities!

So why is duplicate area name support so exciting?

Well, for one, it was just plain annoying when accidentally using a duplicate area name in older versions of Autoprefixer. It would break in IE and, in older versions of Autoprefixer, it would fail silently.

The main reason it is exciting though is that it opens up a whole new world of IE-friendly CSS Grid possibilities!

Use modifier classes to adjust a grid template

This was the use case that really made me want to get duplicate area name support into Autoprefixer. Think about this. You have a typical site with a header, a footer, a main area, and a sidebar down either side.

See the Pen Basic website layout by Daniel Tonon (@daniel-tonon) on CodePen.

Sometimes we want both sidebars, sometimes we want one sidebar, and sometimes we want no sidebars. This was very difficult to manage back when Autoprefixer didn’t support duplicate area names since we couldn’t share area names across multiple grid templates. We would have to do something like this for it to work:

/* Before Duplicate area names were supported - n = no side-bars - f = first sidebar only - s = second sidebar only - fs = first and second sidebars
*/
.main-area { display: grid; grid-template: "content-n" / 1fr;
} .main-area.has-first-sidebar { grid-template: "first-sb-f content-f" / 300px 1fr;
} .main-area.has-second-sidebar { grid-template: "content-s second-sb-s" / 1fr 300px;
}
.main-area.has-first-sidebar.has-second-sidebar { grid-template: "first-sb-fs content-fs second-sb-fs" / 200px 1fr 200px;
} .main-area > .content { grid-area: content-n; /* no side-bars */
} .main-area > .sidebar.first { grid-area: first-sb-f; /* first sidebar only */
} .main-area > .sidebar.second { grid-area: second-sb-s; /* second sidebar only */
} .main-area.has-first-sidebar > .content { grid-area: content-f; /* first sidebar only */
} .main-area.has-second-sidebar > .content { grid-area: content-s; /* second sidebar only */
} .main-area.has-first-sidebar.has-second-sidebar > .content { grid-area: content-fs; /* first and second sidebars */
} .main-area.has-first-sidebar.has-second-sidebar > .sidebar.first { grid-area: first-sb-fs; /* first and second sidebars */
} .main-area.has-first-sidebar.has-second-sidebar > .sidebar.second { grid-area: second-sb-fs; /* first and second sidebars */
}
Autoprefixer translation
/* Before Duplicate area names were supported - n = no sidebars - f = first sidebar only - s = second sidebar only - fs = first and second sidebars
*/ .main-area { display: -ms-grid; display: grid; -ms-grid-rows: auto; -ms-grid-columns: 1fr; grid-template: "content-n" / 1fr;
} .main-area.has-first-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 300px 1fr; grid-template: "first-sb-f content-f" / 300px 1fr;
} .main-area.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 1fr 300px; grid-template: "content-s second-sb-s" / 1fr 300px;
} .main-area.has-first-sidebar.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 200px 1fr 200px; grid-template: "first-sb-fs content-fs second-sb-fs" / 200px 1fr 200px;
} .main-area > .content { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: content-n; /* no side-bars */
} .main-area > .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: first-sb-f; /* first sidebar only */
} .main-area > .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: second-sb-s; /* second sidebar only */
} .main-area.has-first-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: content-f; /* first sidebar only */
} .main-area.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: content-s; /* second sidebar only */
} .main-area.has-first-sidebar.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: content-fs; /* first and second sidebars */
} .main-area.has-first-sidebar.has-second-sidebar > .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: first-sb-fs; /* first and second sidebars */
} .main-area.has-first-sidebar.has-second-sidebar > .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: second-sb-fs; /* first and second sidebars */
}

🤢 Oh yeah, and don’t forget media queries! 🤮

That example was based off actual code that I had to write for an actual project… so yeah, I really wanted to get duplicate area name support into Autoprefixer.

Now that we do have duplicate area name support, we can simplify that code down to something much nicer 😊

/* Duplicate area names now supported! This code will work perfectly in IE with Autoprefixer 9.3.1
*/ .main-area { display: grid; grid-template: "content" / 1fr;
} .main-area.has-first-sidebar { grid-template: "first-sb content" / 300px 1fr;
} .main-area.has-second-sidebar { grid-template: "content second-sb" / 1fr 300px;
} .main-area.has-first-sidebar.has-second-sidebar { grid-template: "first-sb content second-sb" / 200px 1fr 200px;
} .content { grid-area: content;
} .sidebar.first { grid-area: first-sb;
} .sidebar.second { grid-area: second-sb;
}
Autoprefixer translation
.main-area { display: -ms-grid; display: grid; -ms-grid-rows: auto; -ms-grid-columns: 1fr; grid-template: "content" / 1fr;
} .main-area.has-first-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 300px 1fr; grid-template: "first-sb content" / 300px 1fr;
} .main-area.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 1fr 300px; grid-template: "content second-sb" / 1fr 300px;
} .main-area.has-first-sidebar.has-second-sidebar { -ms-grid-rows: auto; -ms-grid-columns: 200px 1fr 200px; grid-template: "first-sb content second-sb" / 200px 1fr 200px;
} .content { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: content;
} .main-area.has-first-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2;
} .main-area.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 1;
} .main-area.has-first-sidebar.has-second-sidebar > .content { -ms-grid-row: 1; -ms-grid-column: 2;
} .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: first-sb;
} .main-area.has-first-sidebar.has-second-sidebar > .sidebar.first { -ms-grid-row: 1; -ms-grid-column: 1;
} .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: second-sb;
} .main-area.has-first-sidebar.has-second-sidebar > .sidebar.second { -ms-grid-row: 1; -ms-grid-column: 3;
}

With that CSS, we are now able to use the has-first-sidebar and has-second-sidebar classes on the grid element to modify what grid template the browser uses. We no longer have to worry about defining exactly what grid grid cells are placed in.

Assign components reusable area names

One of the limitations of being forced to use unique area names was that components could not be given a single, consistent re-usable area name. We were forced to come up with unique area names for every grid.

Now that Autoprefixer has duplicate area name support, that limitation is gone. We can provide every component with a single area name that is based on their component name. We can then reference that one area name whenever we want to place that component inside a grid layout.

/* header.scss */
.header { grid-area: header;
} /* nav.scss */
.nav { grid-area: nav;
} /* sidebar.scss */
.sidebar { grid-area: sidebar;
} /* content.scss */
.content { grid-area: content;
} /* subscribe.scss */
.subscribe { grid-area: subscribe;
} /* footer.scss */
.footer { grid-area: footer;
} /* layout.scss */
.single-sidebar-layout { display: grid; grid-template-areas: "header header" "nav content" "subscribe content" "footer footer";
} .double-sidebar-layout { display: grid; grid-template-areas: "header header header" "nav content sidebar" "nav subscribe sidebar" "footer footer footer";
}
Autoprefixer translation
/* header.scss */
.header { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column-span: 2; grid-area: header;
} .double-sidebar-layout > .header { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column-span: 3;
} /* nav.scss */
.nav { -ms-grid-row: 2; -ms-grid-column: 1; grid-area: nav;
} .double-sidebar-layout > .nav { -ms-grid-row: 2; -ms-grid-row-span: 2; -ms-grid-column: 1;
} /* sidebar.scss */
.sidebar { -ms-grid-row: 2; -ms-grid-row-span: 2; -ms-grid-column: 3; grid-area: sidebar;
} /* content.scss */
.content { -ms-grid-row: 2; -ms-grid-row-span: 2; -ms-grid-column: 2; grid-area: content;
} .double-sidebar-layout > .content { -ms-grid-row: 2; -ms-grid-column: 2;
} /* subscribe.scss */
.subscribe { -ms-grid-row: 3; -ms-grid-column: 1; grid-area: subscribe;
} .double-sidebar-layout > .subscribe { -ms-grid-row: 3; -ms-grid-column: 2;
} /* footer.scss */
.footer { -ms-grid-row: 4; -ms-grid-column: 1; -ms-grid-column-span: 2; grid-area: footer;
} .double-sidebar-layout > .footer { -ms-grid-row: 4; -ms-grid-column: 1; -ms-grid-column-span: 3;
} /* layout.scss */
.single-sidebar-layout { display: -ms-grid; display: grid; grid-template-areas: "header header" "nav content" "subscribe content" "footer footer";
} .double-sidebar-layout { display: -ms-grid; display: grid; grid-template-areas: "header header header" "nav content sidebar" "nav subscribe sidebar" "footer footer footer";
}

Here’s what we’ve got. Note that this should be viewed in IE.

See the Pen component-area-name technique by Daniel Tonon (@daniel-tonon) on CodePen.

Duplicate area name limitation

There is one fairly common use case that Autoprefixer still can’t handle at the moment. When the parent selector of the grid cell does not match up with the grid template selector, it tries to resolve a duplicate area name:

.grand-parent .mother { grid-template-areas: "child";
} .grand-parent .father { grid-template-areas: "child child";
} /* This will work */
.grand-parent .mother .child { grid-area: child;
} /* This does not work because: - ".uncle" != ".grand-parent .mother" - ".uncle" != ".grand-parent .father" - "child" is a duplicate area name
*/
.uncle .child { grid-area: child;
}

Here is a more realistic scenario of the current limitation in Autoprefixer’s algorithm:

.component .grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr;
} /* This rule triggers duplicate area name conflicts. */
.component.modifier .grid { grid-template-areas: "one ... two"; grid-template-columns: 1fr 1fr 1fr;
} /* This does not work because: - ".component" != ".component .grid" - ".component" != ".component.modifier .grid" - area names "one" and "two" both have duplicate area name conflicts
*/
.component .cell-one { grid-area: one;
} .component .cell-two { grid-area: two;
}

There are really only three ways of resolving this conflict at the moment.

Option 1: Remove the parent selector from child elements

Without any safeguards in place for scoping styles to a particular component, this is by far the most dangerous way to resolve the issue. I don’t recommend it.

.component .grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr;
} .component.modifier .grid { grid-template-areas: "one ... two"; grid-template-columns: 1fr 1fr 1fr;
} .cell-one { grid-area: one;
} .cell-two { grid-area: two;
}
Autoprefixer translation
.component .grid { display: -ms-grid; display: grid; grid-template-areas: "one two"; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} .component.modifier .grid { grid-template-areas: "one ... two"; -ms-grid-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
} .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one;
} .component.modifier .grid > .cell-one { -ms-grid-row: 1; -ms-grid-column: 1;
} .cell-two { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: two;
} .component.modifier .grid > .cell-two { -ms-grid-row: 1; -ms-grid-column: 3;
}

Option 2: Go back to using unique area names

This solution is pretty ugly, but if you have no control over the HTML, then this is probably the best way of handling the issue.

.component .grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr;
} .component .cell-one { grid-area: one;
} .component .cell-two { grid-area: two;
} .component.modifier .grid { grid-template-areas: "modifier_one ... modifier_two"; grid-template-columns: 1fr 1fr 1fr;
} .component.modifier .cell-one { grid-area: modifier_one;
} .component.modifier .cell-two { grid-area: modifier_two;
}
Autoprefixer translation
.component .grid { display: -ms-grid; display: grid; grid-template-areas: "one two"; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} .component .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one;
} .component .cell-two { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: two;
} .component.modifier .grid { grid-template-areas: "modifier_one ... modifier_two"; -ms-grid-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
} .component.modifier .cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: modifier_one;
} .component.modifier .cell-two { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: modifier_two;
}

Option 3: Use a BEM-style naming convention

Yep, if you use the BEM naming convention (or something similar), this will practically never be an issue for you. This is easily the preferred way of dealing with the issue if it’s an option.

.component__grid { display: grid; grid-template-areas: "one two"; grid-template-columns: 1fr 1fr;
} .component__grid--modifier { grid-template-areas: "one ... two"; grid-template-columns: 1fr 1fr 1fr;
} .component__cell-one { grid-area: one;
} .component__cell-two { grid-area: two;
}
Autoprefixer translation
.component__grid { display: -ms-grid; display: grid; grid-template-areas: "one two"; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} .component__grid--modifier { grid-template-areas: "one ... two"; -ms-grid-columns: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr;
} .component__cell-one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one;
} .component__grid--modifier > .component__cell-one { -ms-grid-row: 1; -ms-grid-column: 1;
} .component__cell-two { -ms-grid-row: 1; -ms-grid-column: 2; grid-area: two;
} .component__grid--modifier > .component__cell-two { -ms-grid-row: 1; -ms-grid-column: 3;
}

I have some issues with BEM, but with a few tweaks to the syntax, it can be a really great way to control CSS specificity and scoping.

Other Autoprefixer updates

While I’m here, I’ll give you an update on a couple of other developments that have occurred in Autoprefixer since I wrote the original CSS Grid in IE series.

Before we dive in though, here is how to set things up in CodePen in case you want to follow along with your own experiments.

Using Autoprefixer Grid translations in CodePen

CodePen has already upgraded to version 9.3.1 of Autoprefixer. You will now easily be able to integrate IE-friendly CSS Grid styles into your pens. First, make sure that Autoprefixer is enabled in the CodePen settings (Settings > CSS > [Vendor Prefixing] > Autoprefixer).

Step 1: Turn on Autoprefixer in CodePen

Then add the all new /* autoprefixer grid: on */ control comment to the top of the CSS Panel. I will dive into this awesome new feature a bit more later.

Step 2: Add the control comment

You can now write modern IE-friendly CSS Grid code and CodePen will automatically add in all of the IE prefixes for you.

“View compiled CSS” button
The compiled CSS view

In order to actually test your pens in IE though, you will need to view the pen in “Debug Mode” (Change View > Debug Mode). The pen will need to be saved before you will have access to this view.

Enabling Debug Mode for testing in IE

If you’d like to try out a tool that shows you real-time Autoprefixer output, try the online tool just for that. Input CSS on the left. It will output Autoprefixer’s translated CSS on the right as you type.

autoprefixer.github.io

New Autoprefixer control comments

We don’t always have the ability to alter the Autoprefixer configuration settings. If you have ever tried to do some IE-friendly CSS Grid experiments in CodePen in the past, you will know the pain of not having direct access to the Autoprefixer settings. There are also some frameworks like Create React App and Angular that don’t allow users to alter the Autoprefixer settings. There was also a bit of a skill barrier that prevented some users from using Grid because they were unsure of how to enable Grid translations.

This limitation was causing pain for many users but then Andrey Alexandrov submitted a pull request that introduced a new control comment. This new control comment gave users the ability to easily turn grid translations on and off from inside the CSS file. This was far easier than doing it through configuration settings. It was also accessible to all users no matter how they compile their CSS.

Adding /* autoprefixer grid: on */ will enable grid translations for that entire block while /* autoprefixer grid: off */ will disable grid translations for that block. Only the first grid control comment in a block will be applied.

/* Globally enable grid prefixes */
/* autoprefixer grid: on */ .grid { display: grid;
} .non-ie .grid { /* Turn off grid prefixes but only for this block */ /* autoprefixer grid: off */ display: grid; /* Grid control comments affect the whole block. This control comment is ignored */ /* autoprefixer grid: on */ grid-column: 1;
}

The above code translates into the following (I’ve filtered out the explanation comments):

/* autoprefixer grid: on */ .grid { display: -ms-grid; display: grid;
} .non-ie .grid { /* autoprefixer grid: off */ display: grid; /* autoprefixer grid: on */ grid-column: 1;
}

@supports can disable grid translations

The new control comments aren’t the only way to selectively prevent Autoprefixer from outputting grid translation code.

Autoprefixer will never be able to support implicit grid auto-placement. If you use an @supports statement that checks for something like grid-auto-rows: 0, Autoprefixer will not output Grid translations for code entered inside that statement.

.prefixed .grid { display: -ms-grid; display: grid;
} /* Checking grid-auto-* support prevents prefixes */
@supports (grid-auto-rows: 0) { .modern .grid { display: grid; }
} /* Checking basic grid support still outputs prefixes */
@supports (display: grid) { .still-prefixed .grid { display: -ms-grid; display: grid; }
}

To support IE, Autoprefixer can generate something like 50 lines of extra CSS sometimes. If you are writing Grid code inside an @supports statement, you will want IE translations to be turned off to reduce the weight of your CSS. If you don’t want to use @supports (grid-auto-rows: 0) then you can use a control comment inside the @supports statement instead.

@supports (display: grid) { .prefixed .grid { display: -ms-grid; display: grid; }
} @supports (display: grid) { /* autoprefixer grid: off */ .modern .grid { display: grid; }
}

Autoprefixer now inherits grid-gaps

In the original article series, I said that Autoprefixer was unable to inherit grid-gap values. In version 9.1.1, grid-gap values were able to inherit through media queries. In version 9.3.1, they have become inheritable through more specific selectors as well.

.grid { display: grid; grid-gap: 20px; /* grid-gap is stated here */ grid-template: "one two" / 1fr 1fr;
} @media (max-width: 600px) { .grid { /* grid-gap is now inhereited here */ grid-template: "one" "two" / 1fr; }
} .grid.modifier { /* grid-gap is now inhereited here as well */ grid-template: "one" "two" / 1fr;
} .one { grid-area: one; }
.two { grid-area: two; }
Autoprefixer translation
.grid { display: -ms-grid; display: grid; grid-gap: 20px; /* grid-gap is stated here */ -ms-grid-rows: auto; -ms-grid-columns: 1fr 20px 1fr; grid-template: "one two" / 1fr 1fr;
} @media (max-width: 600px) { .grid { /* grid-gap is now inhereited here */ -ms-grid-rows: auto 20px auto; -ms-grid-columns: 1fr; grid-template: "one" "two" / 1fr; }
} .grid.modifier { /* grid-gap is now inherited here as well */ -ms-grid-rows: auto 20px auto; -ms-grid-columns: 1fr; grid-template: "one" "two" / 1fr;
} .one { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: one;
} .grid.modifier > .one { -ms-grid-row: 1; -ms-grid-column: 1;
} .two { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: two;
} .grid.modifier > .two { -ms-grid-row: 3; -ms-grid-column: 1;
} @media (max-width: 600px) { .one { -ms-grid-row: 1; -ms-grid-column: 1; } .two { -ms-grid-row: 3; -ms-grid-column: 1; }
}

grid-template: span X; now works

In Part 2 this series, I mentioned that the following syntax doesn’t work:

.grid-cell { grid-column: span 2;
}

This was fixed in version 9.1.1. It now translates into the following:

.grid-cell { -ms-grid-column-span: 2; grid-column: span 2;
}

New warning for mixing manual and area based placement

We had a user complain that Autoprefixer wasn’t handling grid areas correctly. Upon further investigation, we realized that they were applying both a grid-area and a grid-column setting within the same CSS rule.

.grid { display: grid; grid-template-areas: "a b";
} /* This doesn't work very well */
.grid-cell { grid-column: 2; grid-area: a;
}

Either use grid-area on its own, or us grid-column & grid-row. Never use both at the same time.

If you are curious, this is what Autoprefixer outputs for the above code:

.grid { display: -ms-grid; display: grid; grid-template-areas: "a b";
} /* This doesn't work very well */
.grid-cell { -ms-grid-row: 1; -ms-grid-column: 1; -ms-grid-column: 2; grid-column: 2; grid-area: a;
}

There is one exception to this. You may need a grid cell to overlap other grid cells in your design. You want to use grid-template-areas for placing your grid cells due to how much easier Autoprefixer makes the overall cell placement. You can’t really create cell overlaps using grid-template-areas though. To create this overlap, you can use grid-[column/row]-end: span X; after the grid-area declaration to force the overlap.

.grid { display: grid; grid-template-areas: "a . ." "a b b" "a . ."; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr;
} .grid-cell-a { grid-area: a; /* place cell span after the grid-area to force an overlap */ grid-column-end: span 2;
}

See the Pen column-span + grid-area experiment by Daniel Tonon (@daniel-tonon) on CodePen.

However if you have declared grid gaps in your grid, you will need to write the column/row span prefix manually while taking the extra columns/rows generated by Autoprefixer into consideration (IE doesn’t support grid-gap). There is an issue for this on GitHub.

.grid { display: grid; grid-template-areas: "a . ." "a b c" "a . ."; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr; grid-gap: 10px;
} .grid-cell-a { grid-area: a; /* IE column span added manually */ -ms-grid-column-span: 3; /* IE spans 2 columns + the gap */ grid-column-end: span 2; /* Modern browsers only span 2 columns */
}

See the Pen column-span + grid-area experiment 2 by Daniel Tonon (@daniel-tonon) on CodePen.

This technique currently produces a warning message in Autoprefixer that can’t easily be hidden. An issue for this is on GitHub.

New warning when using [align/justify/place]-[content/items]

Unfortunately. IE does not have the ability to align grid cells from the parent container. The only way to align grid cells in IE is by using the -ms-grid-row-align and the -ms-grid-column-align properties. These translate to align-self and justify-self in modern day grid syntax.

The following properties will trigger a warning in Autoprefixer if used in conjunction with a CSS Grid property:

  • align-items
  • align-content
  • justify-items
  • justify-content
  • place-items
  • place-content

The align-content, justify-content and place-content properties are pretty much impossible to replicate in IE. The align-items, justify-items and place-items properties, on the other hand, are quite easy to replicate using their self equivalents on the child elements (place-self support was added in 9.3.0).

/* [align/justify/place]-items is *NOT* IE friendly */ .align-justify-items { display: grid; align-items: start; justify-items: end;
} .place-items { display: grid; place-items: start end;
} /*[align/justify/place]-self *IS* IE friendly */ .align-justify-grid { display: grid; }
.align-justify-grid > * { align-self: start; justify-self: end;
} .place-grid { display: grid; }
.place-grid > * { place-self: start end;
}
Autoprefixer translation
/* [align/justify/place]-items is *NOT* IE friendly */ .align-justify-items { display: -ms-grid; display: grid; align-items: start; justify-items: end;
} .place-items { display: -ms-grid; display: grid; place-items: start end;
} /*[align/justify/place]-self *IS* IE friendly */ .align-justify-grid { display: -ms-grid; display: grid; }
.align-justify-grid > * { -ms-grid-row-align: start; align-self: start; -ms-grid-column-align: end; justify-self: end;
} .place-grid { display: -ms-grid; display: grid; }
.place-grid > * { -ms-grid-row-align: start; -ms-grid-column-align: end; place-self: start end;
}

.grid { [align/justify/place]-items } and .grid > * { [align/justify/place]-self } are generally quite interchangeable with one another. This substitution doesn’t always work, but in most cases, the two methods tend to act in much the same way.

Below is a pen demonstrating the difference between the IE friendly alignment method and the IE unfriendly alignment method. In modern browsers they look identical, but in IE one looks the same as the modern browsers and one does not.

See the Pen place-items experiment by Daniel Tonon (@daniel-tonon) on CodePen.

That’s all, folks

I hope you have enjoyed reading about the awesome new improvements the Autoprefixer community has made to the project over the past few months. The new control comments make enabling and disabling grid translations an absolute breeze. The new grid-areas system is also exciting. I love all the new IE-friendly CSS Grid options that the new areas system opens up, and I think you will too. 🙂

Article Series:

  1. Debunking common IE Grid misconceptions
  2. CSS Grid and the new Autoprefixer
  3. Faking an auto-placement grid with gaps
  4. Duplicate area names now supported! (This Post)

The post CSS Grid in IE: Duplicate area names now supported! appeared first on CSS-Tricks.

Exclusions will hopefully be like more powerful grid-friendly floats

Exclusions (which are currently in a “working draft” spec as I write) are kinda like float in that they allow inline content to wrap around an element. But not exactly a float. Chen Hui Jing has an excellent explanation:

An exclusion element is a block-level element which is not a float, and generates an exclusion box. An exclusion element establishes a new block formatting context.

An element becomes an exclusion when its wrap-flow property is computed to something other than its initial value of auto. When an element becomes an exclusion, inline content will wrap around the exclusion areas, but within their own formatting contexts.

Source: Chen’s article

Support is limited to Edge and IE (again, as I write):

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Opera Firefox IE Edge Safari
No No No 10* 12* No

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
No No No No No No

Chen makes a great case for why they are useful, but another round of discussion has cropped up lately as well. Rob Weychert documents a simple layout situation in which an image is floated left and text is wrapping around it:

Source: Rob’s article

As those light red bars indicate, Rob has set up some display: grid; columns to align elements in the article to those axes. A classic “editorial layout” indeed. But there really is no good mechanism to place that image onto the grid and maintain the wrapping. By placing both the content and the image into separate grid items, you don’t get the wrapping. You can use float, but that’s not using the grid.

Rachel Andrew chimed in that the answer is CSS exclusions. While Rob’s example ultimately had to use floats, Rachel re-did it with exclusions. Exclusions make the code much simpler.

/* with floats, replicating exactly what the grid is doing */
img { float: left; width: calc( 3 * ((100% - 50px - 15em) / 6) + 50px + 2em );
} /* with exclusions, using the grid */
img { grid-row: 2; grid-column: 1 / 3; -ms-wrap-flow: both;
}

Perhaps we can chime in with thumbs up on Rachel’s call to see what’s up with the status of the spec and with other author use cases.

The post Exclusions will hopefully be like more powerful grid-friendly floats appeared first on CSS-Tricks.

Simple Named Grid Areas

I think of named grid areas in CSS Grids as bring-your-own syntactic sugar. You don’t absolutely need them (you could express grid placement in other ways), but it can make that placement more intuitive. And, hey, if I’m wrong about that, correct me in the comments.

Say you set up a 3-column grid:

.grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr;
}

No rows defined there; those are implicit and will appear as needed. We could define them, we just aren’t, because like most situations in web design, we don’t care how tall the items are — the height will grow as needed to accomodate the content.

Now, how do we place something in that very top-left position in the grid? We could tell the grid to place it there like this:

.item { grid-column: 1 / 2; /* start at the first grid column line and end at the second */
}

That works, although that .item better be the first child of .grid. Otherwise, something else may implicitly be placed there and .item will kick down to the next open row. If we wanted to be super sure to place it in the top-left, we could do the row as well:

.item { grid-column: 1 / 2; grid-row: 1 / 2;
}

Now it will be in the top-left for sure, even if other items are explicitly placed there (they’ll just overlap). We can even shorten things up with the grid-area property:

.item { grid-area: 1 / 1 / 2 / 2;
}

All those 1’s and 2’s might be intuitive enough for now, but the numbers become a bit much in more complex grids involving both column and row placement.

Check this. While we are defining the columns, we can name them with a separate property:

.grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr; grid-template-areas: "pro a b" "pro c d";
}

Every quoted group in grid-template-areas is a row. Inside are names I just made up. Could be just about anything, as long as it makes sense to you. See how the word “pro” is repeated twice there on two rows? That’s important, as it’s saying that we could place a grid item where that value “pro” is and it will be in the first of three columns and span two rows. Pretty intuitive, yeah?

We place it like this:

.pro-features { /* rather than */ grid-area: 1 / 1 / 2 / 3; /* we can now do */ grid-area: pro;
}

Here’s that simple example:

See the Pen Simple Named Grid Areas by Chris Coyier (@chriscoyier) on CodePen.

Want to get even more descriptive with a grid? Try drawing it in your CSS comments.

The post Simple Named Grid Areas appeared first on CSS-Tricks.

Understanding the difference between grid-template and grid-auto

Ire Aderinokun:

Within a grid container, there are grid cells. Any cell positioned and sized using the grid-template-* properties forms part of the explicit grid. Any grid cell that is not positioned/sized using this property forms part of the implicit grid instead.

Understanding explicit grids and implicit grids is powerful. This is my quicky take:

  • Explicit: you define a grid and place items exactly where you want them to go.
  • Implicit: you define a grid and let items fall into it as they can.

Grids can be both!

Direct Link to ArticlePermalink

The post Understanding the difference between grid-template and grid-auto appeared first on CSS-Tricks.

Don’t use empty or low content for your design system grid examples

Dave and I had Jen Simmons on ShopTalk the other day. Jen was talking about Intrinsic Web Design and how one of the core tenets of it is grids with rows and columns that don’t necessarily change at the same rate or ones that have essentially different rules for how they behave.

For example, take this (contrived) grid setup:

.grid { display: grid; grid-template-columns: 1fr minmax(50px, 100px) 20% auto;
}

Each of those columns will behave differently.

I’m just wrapping my head about this, and definitely don’t fully understand it. Here’s what it seems like to me, numbered 1-4 based on the “strength” (I guess?) of the width.

.grid { display: grid; grid-template-columns: 1fr /* #4 - Weakest, will fill remaining space */ minmax(50px, 100px) /* #3 - Will only start changing when other columns force it */ 20% /* #1 - Definite size, steady */ auto /* #2 - Indefinite size, entirely based on content, pushy */ ;
}

This is much different from quite a long history of how we’ve set up grid columns in the past. Float-based grids typically use percentages (a definite size) to set columns. Same with inline-block-based grids, typically.

Even with grid, if you set up all your columns with all percentages or all fractional units, you’d likely have a steady grid in which the content inside won’t mess with sizing. But Jen is saying that it’s interesting to have a grids where the content has a say in how they size. Embrace it. Sounds fun to me.

But anyway, say you’re setting up a grid that uses mixed values for column widths like this. Don’t do that with totally empty columns, otherwise, you’ll get a false sense of how those columns will behave.

Just look at this demo where these four grids have the exact same setup and all that is different is the amount of text in each column.

See the Pen Different Collapse Rates of Different Column Width Values by Chris Coyier (@chriscoyier) on CodePen.

Cool’n’weird.

The post Don’t use empty or low content for your design system grid examples appeared first on CSS-Tricks.

Little Tip: Draw Your Grid in ASCII in Your CSS Comments for Quick Reference

Say you declared a grid like this:

body { display: grid; grid-template-columns: min-content 1fr; grid-template-rows: min-content auto min-content;
}

This depends on content, for sure, but how it’s likely to play out is like this:

+---+-------------+
| | |
| | |
+-----------------+
| | |
| | |
| | |
| | |
| | |
| | |
+-----------------+
| | |
+---+-------------+

That’s really easy to draw out quick in ASCIIFlow Infinity.

Now you want to place elements in that grid, and arguably the easiest way to do that is to specify the grid rows/columns they should start/end at.

/* grid-area: row-start / column-start / row-end / column end */ .logo { grid-area: 1 / 1 / 2 / 2;
} .site-header { grid-area: 1 / 2 / 2 / 3;
} .sidebar-nav { grid-area: 2 / 1 / 3 / 2;
} .main-content { grid-area: 2 / 2 / 3 / 3;
} .site-footer { grid-area: 3 / 1 / 4 / 3;
}

There are other ways to do this. You could use longhand CSS properties. You could name the areas. But say you like doing it this way because it is succinct or whatever. That’s where the ASCII is useful! Leave it in a CSS comment and number the lines.

/* 1 2 3
1 +---+-------------+ | | | | | |
2 +-----------------+ | | | | | | | | | | | | | | | | | |
3 +-----------------+ | | |
4 +---+-------------+
*/

Now you’ve got an visual reference to pick out those grid numbers from.

If you like native apps and wanna get real fancy, there is Monodraw.

The post Little Tip: Draw Your Grid in ASCII in Your CSS Comments for Quick Reference appeared first on CSS-Tricks.

CSS Grid in IE: Faking an Auto-Placement Grid with Gaps

This is the third and final part in a three-part series about using CSS grid safely in Internet Explorer 11 (IE11) without going insane.

In Part 1, I covered some of the common misconceptions that people have about IE11’s native CSS grid implementation. In Part 2, I showed the world how easy it actually is to write IE-friendly CSS grid code.

Today, I’m going step away from CSS grid for a moment to show you a flexbox technique that replicates basic CSS grid auto-placement functionality. This CSS grid replica will even look like a grid-gap has been applied to it. I need to be super clear though: this is not about how to make actual CSS grid auto-placement work in IE.

Article Series:

  1. Debunking Common IE Grid Misconceptions
  2. CSS Grid and the new Autoprefixer
  3. Faking an auto-placement grid with gaps (This Post)

How to make a fake grid with cell gaps

Step 1: HTML

I’ll use this basic HTML as an example:

<div class="grid-wrapper"> <div class="grid"> <div class="grid-cell"></div> <div class="grid-cell"></div> <div class="grid-cell"></div> <div class="grid-cell"></div> <div class="grid-cell"></div> <div class="grid-cell"></div> </div> </div>

Step 2: Border-box box sizing

The first thing that we need to do in the CSS is make sure that all of the boxes are being sized based on border-box rather than content-box. The best way to do that is using the box-sizing: border-box inheritance technique:

html { box-sizing: border-box;
} *, *::before, *::after { box-sizing: inherit;
}

That will be applied globally. If you are working on an an existing project that doesn’t have box-sizing set to border-box, then change html in the snippet to a selector that targets the element you want to turn into a grid.

Step 3: Flex

Next, you will need to turn on some flexbox settings:

.grid { /* Forces equal cell heights */ display: flex; flex-wrap: wrap;
}

Step 4: Widths

Now, set up your column widths. We’ll make ourselves a simple three-column grid:

.grid-cell { /* Sets column count */ width: calc(100% / 3); /* calc() method */ width: 33.33%; /* percentage method */
}

The calc() method allows the column widths to be changed a bit more easily. You state how many columns you want and the browser does the math for you. This is especially handy for when you need a larger number of columns, like 7 or 8. The browser support for calc() is strong but not as strong as a raw percentage value which has been supported by browsers since the dawn of CSS.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Opera Firefox IE Edge Safari
19* 15 4* 10 12 6*

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
6.0-6.1* 46 No 67 67 60

The percentage method has slightly better browser support and can be a bit more stable in IE. If you don’t need to support Opera Mini, I would still recommend going with the calc() method first. Test in IE, and if the layout breaks, first try using 99.999% instead of 100% in the calc function (calc(99.999% / 3)). If that doesn’t work, then try switching to the percentage method. I will be using the calc() method in all of my examples. Note that if you are using a CSS pre-processor like SCSS, you can have the best of both worlds by getting the pre-processor to do the math for you. This comes at the cost of not being as easily able to edit or review the column counts in browser dev tools.

/* Set column count using SCSS */
.grid-cell { width: (100% / 3);
} /* CSS output into the browser */
.grid-cell { width: 33.3333333333%;
}

Let’s give the grid cells some height and an inner box-shadow so that we can see what’s going on. I’m not adding border — I’ll be using that later. 😉

.grid-cell { /* So that we can see the grid cells */ box-shadow: inset 0 0 0 1px #000; height: 100px;
} .grid-wrapper { /* Allows us to see the edges of the grid */ box-shadow: 0 0 10px 2px green;
}

You should now have something that looks like this:

A basic 3 x 2 grid with no gaps

That’s boring though, right? Everyone knows how to do that. Where are these grid gaps I keep talking about? I want my gaps!!!

Step 5: Border

Here’s where we get to the interesting part. Since we set box-sizing to border-box, the 33.33% width now includes the border. What this means is that we can start safely mixing fixed and percentage based units! 😃

.grid { /* Creates an equal outer gap */ padding: 20px 0 0 20px;
} .grid-cell { /* Creates gaps */ border: 0 solid transparent; border-width: 0 20px 20px 0;
}

This results in something that looks like a grid with equal spacing everywhere:

A 3 x 2 grid with equal space between each cell and the outer edges of the grid

To help give you a better idea of what is going on, take a look at the following image:

Color-coded diagram of the grid

The blue area on the top and left sides of the grid is the padding for the .grid element. The yellow outlines show the area that each .grid-cell element takes up. The red areas on the bottom and right sides of each cell are the border for each .grid-cell element.

That might be the look that you actually want. On the other hand, that isn’t what a grid with a grid-gap setting looks like. That is why we have another step.

Step 6: Margin and overflow

In order to get the grid pressing hard up against the edges of its container, we need a bit of help from negative margins and overflow: hidden:

.grid { /* Pulls grid cells hard against edges */ margin: -20px;
} .grid-wrapper { /* Prevents odd margin behavior */ overflow: hidden;
}

We need to apply overflow: hidden to prevent this from happening:

Top and bottom negative margin is ignored if overflow is not hidden

Applying the negative margin and overflow: hidden will get us to this beautiful recreation of basic grid-gap functionality:

A 3 x 2 grid that looks identical to a CSS grid with a gap setting

The top and left padding on the grid is actually optional. You can opt to leave off the padding and change the margin value as shown below if you prefer:

.grid { /* Margin needs to be this if leaving off the top and left .grid padding */ margin: 0 -20px -20px 0;
}

But, hold on! The job isn’t quite over yet. Take a look at what happens if we add a background color to one of the grid cells:

A pink background applied to the top left cell overflows into the grid gap

Not exactly what we want, so there is one more step.

Step 7: background-clip

In order to prevent the grid cell background from bleeding into our fake grid-gap, we need to add background-clip: padding-box to it.

.grid-cell { /* Prevents background bleed */ background-clip: padding-box;
}

Now we have this:

The background bleed has been fixed!

If you have never heard of the background-clip property before, you might be worried about browser support… well don’t be. background-clip has been around since IE9!

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

Chrome Opera Firefox IE Edge Safari
15 10.5 4 9 12 7

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
7.0-7.1 10 all 4.4 67 60

Step 8: Media Queries!

Most of the time, grids need to be able to change the number of columns that they have as they grow and shrink. Using other methods can be a massive pain. You might have to calculate a bunch of nth-childs so you can remove the right margin or whatever. With this method, you only have to change a single value! 😃

.grid-cell { /* Sets the default column count */ width: calc(100% / 1); /* 1 column */
} @media (min-width: 400px){ .grid-cell { width: calc(100% / 2); /* 2 columns */ }
} @media (min-width: 600px){ .grid-cell { width: calc(100% / 3); /* 3 columns */ }
}
3 x 2 grid with gaps
2 x 3 grid with gaps
1 x 6 grid with gaps

Here’s how it looks when we put it all together:

See the Pen Fake grid by Daniel Tonon (@daniel-tonon) on CodePen.

Ain’t nobody got time for dat!

That’s a lot of work compared to what modern Grid can do in just three lines of CSS! To make the task easier, I created an SCSS-powered mixin I call Gutter Grid. Once Gutter Grid is installed in the project, you can quickly create a three-column grid with 20px gaps using the following SCSS code:

.grid-wrapper { overflow: hidden; /* Need this for the chrome bug */
} .grid { @include grid($cols: 3, $gutter: 20px);
}

You can write it even shorter like this if that feels too verbose:

.grid-wrapper { overflow: hidden;
} .grid { @include grid(3, 20px);
}

Gutter Grid comes pre-built with a few sets of breakpoints so you may not have to write any breakpoints at all if your grid spans the whole page! If you do need custom breakpoints, though, then Gutter Grid lets you easily customize them like so:

// Verbose custom breakpoints
@include grid($cols: 7, $gutter: 20px, $breakpoints: ( 4 : 960px, // At 960px or below, there will be 4 columns 2 : (max, 600px), // You can use mq-scss syntax here as well 1 : 480px,
)); // Short version @include grid(7, 20px, ( 4 : 960px, 2 : 600px, 1 : 480px,
));

As you might have noticed in the example, Gutter Grid also supports the same media query syntax that this thing called mq-scss uses. If you are wondering what that is, well, it’s a Sass mixin that I created that makes writing and managing media queries about a million times easier. Using mq-scss statements to dictate column count allows for very fine control over when the column count changes.

Adding shadows to the grid cells

Since we are working with shadows now, I’ll take the box shadow off of the example image. Our starting grid looks like this now:

A basic 3 x 2 grid with gaps and a green border around the outside

If we try to add an outer box-shadow to each grid cell right now… well it doesn’t look so good:

Adding shadows to the grid cells causes the shadows to be out of alignment

Let’s fix that.

Step 1: New HTML

In order to create nice shadows, we need to add an extra div inside each grid cell. You can’t really use ::before or ::after for this since they are unable to contain HTML content inside of them.

<div class="grid-wrapper"> <div class="grid"> <div class="grid-cell"> <div class="grid-cell-inner"></div> </div> <div class="grid-cell"> <div class="grid-cell-inner"></div> </div> <div class="grid-cell"> <div class="grid-cell-inner"></div> </div> <div class="grid-cell"> <div class="grid-cell-inner"></div> </div> <div class="grid-cell"> <div class="grid-cell-inner"></div> </div> <div class="grid-cell"> <div class="grid-cell-inner"></div> </div> </div>
</div>

Step 2: Flex it

Now, we need to make each grid cell a flex container. This will allow the inner part of the grid cell to take up the full height of its parent. We will also need to set the inner element to a width of 100%. This ensures that it will take up the full dimensions of its parent, both horizontally and vertically:

.grid-cell { /* Forces inner to take up full grid cell height */ display: flex;
} .grid-cell-inner { /* Forces inner to take up full grid cell width */ width: 100%;
}

Let’s see what we get if we try adding box shadows to the inner elements:

.grid-cell-inner { box-shadow: 0 0 10px 3px blue;
}
Box shadows appear around grid cells but are getting cut off

That’s much nicer, but it is still not quite there yet. The hidden overflow that we are using to prevent the Chrome bug is getting in the way.

Step 3: Hacky padding

So, we need to allow overflow but still avoid this Chrome bug. The only other safe way I’ve found to do that is with padding. By adding 1px of padding to the top and bottom of the outer grid wrapper element, it will fix the Chrome bug.

.grid-wrapper { /* Prevents odd margin behaviour in Chrome */ padding: 1px 0;
}

This comes at the expense of having an extra 1px of space at the top and bottom of the grid. The image below demonstrates how this ends up looking. The shadows have been lightened to show the 1px gap more clearly.

1px of padding at the top and bottom of the grid

Note: You can avoid the 1px of top padding by opting not to include the top padding gap value on the grid element. The 1px of bottom padding can’t be avoided though.

A border width applied to the outer grid wrapper will also work, so technically I didn’t need to apply the padding to the example above. Most of the time, if we are applying a shadow to grid cells, then we probably don’t want to see a border wrapped around them. The above example was more demonstrating how minor the padding is.

This is what the grid looks like without the outer border:

3 x 2 shadow cell grid
2 x 3 shadow cell grid
1 x 6 shadow cell grid

Here is a Pen showing the final product:

See the Pen Fake grid with shadows by Daniel Tonon (@daniel-tonon) on CodePen.

Gutter Grid shadows

Let’s cover how to add shadows on Gutter Grid cells. You can use the same HTML structure we used in the previous example.

Now, apply this SCSS to create a three-column grid that has a 20px gutter:

.grid { @include grid(3, 20px, $inners: true);
}

This new $inners: true property tells Gutter Grid that the grid cells each have a single child element that needs to take up the full height and width of its parent grid cell.

Instead of using overflow: hidden, use 1px of bottom padding on the wrapper element.

.grid-wrapper { padding-bottom: 1px;
}

Gutter Grid will not output a top outer gutter if it doesn’t need to. This helps avoid issues around the Chrome negative margin bug. After all, if there is no top outer gutter to negate with a faulty negative margin, then there is no bug to worry about. The bottom outer gutter is still a problem, though, and that is why we need the 1px of bottom padding. This 1px of bottom padding tends to be barely noticeable (if at all), so don’t worry about it too much.

Now, add your shadows and you’ve got yourself a Gutter Grid with shadow cells!

.grid-cell-inner { box-shadow: 0 0 10px 3px blue;
}
3 x 2 shadow cell grid

I’ve only scraped the surface of what Gutter Grid can do in this article. Make sure to read the full documentation to learn what else it’s capable of.

We come to the end of our IE grid adventure

I hope you have enjoyed this foray into the world of IE and CSS grid. Make sure to read through Part 1 and Part 2 if you haven’t already. Having read all three articles, you will now be fully equipped to make some truly stunning layouts that look just as good in IE as they do in modern browsers.

If you ever see anyone complaining about not being able to use CSS grid because of IE, you know what to do. Playfully slap them on the head for being so foolish and send them here to get the truth.

Now go forth, my friends, and build some grids! 😃🎉

Article Series:

  1. Debunking Common IE Grid Misconceptions
  2. CSS Grid and the new Autoprefixer
  3. Faking an auto-placement grid with gaps (This Post)

The post CSS Grid in IE: Faking an Auto-Placement Grid with Gaps appeared first on CSS-Tricks.

CSS Grid in IE: CSS Grid and the New Autoprefixer

In Part 1 of this series, I debunked a few misconceptions that many people have around the Internet Explorer (IE) implementation of CSS grid. This article builds on that knowledge. It would be best to go back and read that article first if you haven’t already.

Today I’m going to be tackling the biggest misconception of all: that utilizing the IE implementation of CSS grid is extremely difficult. You can easily use CSS grid in IE right now without having to give it any sort of crappy fallback layout. It really isn’t that hard.

Article Series:

  1. Debunking Common IE Grid Misconceptions
  2. CSS Grid and the new Autoprefixer (This Post)
  3. Faking an auto-placement grid with gaps

Giving IE a crappy fallback layout is a bit of a tough sell to clients. It is especially tough if this is for an intranet where 90% of the users are using IE. If you want IE compatibility, first you need to resign to the fact that you can’t use all of the fancy bells and whistles that can be found in the modern CSS grid spec. Don’t let this get you down though, you would be amazed by how much IE11 can handle, especially if it has some help from Autoprefixer.

Before I get too far into this, you need to know that this isn’t a general “how to use CSS grid” article. This article is for those that understand CSS grid, but are either too afraid or not allowed to use it, thanks to IE.

I’ll be assuming that you already have a good understanding of how to use CSS grid in modern browsers for this article. If you aren’t sure about how to use CSS grid yet, go watch Rachel Andrew’s excellent CSS grid video tutorial series. After that, go play some levels of the browser game Grid Garden to get some hands-on CSS grid experience. Once you understand the basics of how to use CSS grid in modern browsers, come back here and learn how to use it in a way that produces identical results in IE10 and 11.

Setting up Autoprefixer

Before you do anything else, you will want to get Autoprefixer up and running. Autoprefixer is a tool used for automatically adding browser-specific CSS prefixes to your CSS so that you don’t have to. It’s a bit like overview by the creator of Autoprefixer here on CSS Tricks.)

If you have never used Autoprefixer (or any build tool) before, then first install Node on your computer then follow this guide on how to get a basic workflow up and running. The bit in the guide specifically about Autoprefixer is found here. (I recommend the Gulp setup over Grunt if you aren’t sure which to go with.)

If you are already using Autoprefixer in your projects, make sure to update it to the latest version using this command:

npm i autoprefixer@latest -D

Some features used in the latest version of Autoprefixer are not supported in PostCSS version 5. This means that you may also need to update your version of PostCSS to at least version 6. If using Gulp, that means updating gulp-postcss to at least v7.0.0. If using Grunt, you may need to update grunt-postcss to at least v0.9.0.

Once you have an environment up and running, you will need to set the Autoprefixer grid setting to true. Without that setting turned on, Autoprefixer will not be able to do any of the cool stuff that I’m about to show you.

The exact method for turning the grid setting on depends a lot on how you compile your code. If you were using the guide that I linked to earlier, you would have seen this snippet of code:

var processorsArray = [ // snipped for brevity require('autoprefixer')({ browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20'] })
];

Add grid: true to the options to turn grid prefixing on:

var processorsArray = [ // snipped for brevity require('autoprefixer')({ grid: true, browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20'] })
];

By the way, the browser settings in the tutorial are pretty outdated and will be outputting far more prefixes than you actually need. Just going with ">1%" will mean that when a browser dies, Autoprefixer will automatically stop writing prefixes for that browser. It bases browser usage on global browser data retrieved from caniuse.com.

So, these are the Autoprefixer settings that you should end up using:

var processorsArray = [ require('autoprefixer')({ grid: true, browsers: ['>1%'] })
];

Now onto the fun stuff! 😃

Autoprefixer has new super powers!

You may have read Rachel Andrew’s article “Should I try to use the IE implementation of CSS Grid Layout?” That article is all about CSS grid and understanding it’s support in IE10 and 11. It’s a great article and very useful for understanding IE’s limitations. Definitely still worth a read if you haven’t already checked it out. Note that it is extremely outdated in terms of its information on Autoprefixer though.

Autoprefixer has come a long way since Rachel wrote her IE11 CSS grid article and Autoprefixer now supports far more CSS grid translations. Take a look at this new, updated version of Rachel’s table based on Autoprefixer version 8.6.4. Note that items in bold represent a change in Autoprefixer support compared to Rachel’s article:

CSS Grid Property IE10 Implementation Autoprefixer? Notes
grid-template-columns -ms-grid-columns Yes
grid-template-rows -ms-grid-rows Yes
grid-template-areas NA Yes Autoprefixer uses this to understand what the grid looks like but does not add any extra properties.
grid-template NA Yes Shorthand for grid-template-columns, grid-template-rows, and grid-template-areas
grid-auto-columns NA No IE doesn’t support auto-placement
grid-auto-rows NA No IE doesn’t support auto-placement
grid-auto-flow NA No IE doesn’t support auto-placement
grid NA No See this GitHub issue as to why this isn’t supported
grid-row-start -ms-grid-row Yes1 Span syntax requires grid-row-end to be defined
grid-column-start -ms-grid-column Yes1 Span syntax requires grid-column-end to be defined
grid-row-end NA Yes1 grid-row-start must be defined
grid-column-end NA Yes1 grid-column-start must be defined
grid-row NA Yes1
grid-column NA Yes1
grid-area NA Yes2 Autoprefixer translates the grid area into column/row coordinates
grid-row-gap NA Yes3 Generates extra rows/columns in IE.
grid-column-gap NA Yes3 Generates extra rows/columns in IE.
grid-gap NA Yes3 Generates extra rows/columns in IE.
NA -ms-grid-column-span Yes Translated from grid-column-end and grid-area.
NA -ms-grid-row-span Yes Translated from grid-row-end and grid-area.
align-self -ms-grid-row-align Yes
justify-self -ms-grid-column-align Yes

Table disclaimers

I will cover these in far more detail later in the article:

  1. Autoprefixer cannot prefix negative integers.
  2. Each grid element must have unique area names.
  3. Autoprefixer only prefixes grid-gap if both grid-template-areas and grid-template-columns have been defined. It also cannot inherit grid-gap through media queries.

grid-template-areas is your new best friend

As you can see from the updated (and much more positive-looking) table, there are a lot of cool new features in Autoprefixer now. The most important of which is its support for grid-template-areas (and by extension grid-template). By supporting grid-template-areas, Autoprefixer now understands exactly what your grid looks like. This paved the way for Autoprefixer to also support (in a limited capacity) grid-gap.

Note that Autoprefixer still does not support the shortcut grid property. This was an intentional design decision that you can learn more about in this GitHub issue. The short story is that the grid property is not only a shortcut for the templating settings but also the auto-placement settings. Since IE can’t do auto-placement and the grid-template property can essentially do anything that the grid property can do (that IE can handle), it was decided that the grid property wasn’t worth supporting.

Back when Rachel wrote her article, this was the sort of grid code you would need to write in order to support IE:

/* IE-friendly source code 26 November 2016 */
/* Code needed to make Autoprefixer work properly */ .grid { display: grid; grid-template-columns: 1fr 10px 1fr; grid-template-rows: 100px 10px 100px;
} .cell-A { grid-column: 1; grid-row: 1;
} .cell-B { grid-column: 3; grid-row: 1;
} .cell-C { grid-column: 1; grid-row: 3;
} .cell-D { grid-column: 3; grid-row: 3;
}

Now, you can write code like this instead:

/* Today’s IE-friendly source code */
/* Autoprefixer can now make this code IE safe */ .grid { display: grid; grid-gap: 10px; grid-template: "a b" 100px "c d" 100px / 1fr 1fr;
} .cell-A { grid-area: a;
} .cell-B { grid-area: b;
} .cell-C { grid-area: c;
} .cell-D { grid-area: d;
}

Autoprefixer will take the above code and translate it into this much more IE-friendly code for you:

/* Autoprefixer’s IE-friendly translation */ .grid { display: -ms-grid; display: grid; grid-gap: 10px; -ms-grid-rows: 100px 10px 100px; -ms-grid-columns: 1fr 10px 1fr; grid-template: "a b" 100px "c d" 100px / 1fr 1fr;
} .cell-A { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: a;
} .cell-B { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: b;
} .cell-C { -ms-grid-row: 3; -ms-grid-column: 1; grid-area: c;
} .cell-D { -ms-grid-row: 3; -ms-grid-column: 3; grid-area: d;
}

Best of all, you can then simply change the grid-template or grid-template-areas property with a media query and Autoprefixer will automatically update all of the grid cell coordinates for you:

/* Changing a grid-template with a media-query */ .grid { display: grid; grid-gap: 10px; grid-template: "a b" 100px "c d" 100px "e f" 100px / 1fr 1fr;
} @media (min-width: 600px){ .grid { /* Autoprefixer 8.6.4 doesn't inherit grid gaps 🙁 */ grid-gap: 10px; grid-template: "a b c" 100px "d e f" 100px / 1fr 1fr 1fr; }
} .cell-A { grid-area: a;
} .cell-B { grid-area: b;
} .cell-C { grid-area: c;
} .cell-D { grid-area: d;
} .cell-E { grid-area: e;
} .cell-F { grid-area: f;
}

The above gets translated into this IE-friendly code:

/* Autoprefixer’s IE-friendly media query translation */ .grid { display: -ms-grid; display: grid; grid-gap: 10px; -ms-grid-rows: 100px 10px 100px 10px 100px; -ms-grid-columns: 1fr 10px 1fr; grid-template: "a b" 100px "c d" 100px "e f" 100px / 1fr 1fr;
} @media (min-width: 600px) { .grid { /* Autoprefixer 8.6.4 doesn't inherit gaps 🙁 */ grid-gap: 10px; -ms-grid-rows: 100px 10px 100px; -ms-grid-columns: 1fr 10px 1fr 10px 1fr; grid-template: "a b c" 100px "d e f" 100px / 1fr 1fr 1fr; }
} .cell-A { -ms-grid-row: 1; -ms-grid-column: 1; grid-area: a;
} .cell-B { -ms-grid-row: 1; -ms-grid-column: 3; grid-area: b;
} .cell-C { -ms-grid-row: 3; -ms-grid-column: 1; grid-area: c;
} .cell-D { -ms-grid-row: 3; -ms-grid-column: 3; grid-area: d;
} .cell-E { -ms-grid-row: 5; -ms-grid-column: 1; grid-area: e;
} .cell-F { -ms-grid-row: 5; -ms-grid-column: 3; grid-area: f;
} @media (min-width: 600px) { .cell-A { -ms-grid-row: 1; -ms-grid-column: 1; } .cell-B { -ms-grid-row: 1; -ms-grid-column: 3; } .cell-C { -ms-grid-row: 1; -ms-grid-column: 5; } .cell-D { -ms-grid-row: 3; -ms-grid-column: 1; } .cell-E { -ms-grid-row: 3; -ms-grid-column: 3; } .cell-F { -ms-grid-row: 3; -ms-grid-column: 5; }
}

The duplicate media query might look a bit ugly but I assure you that this is the best possible way that Autoprefixer can handle the media query translation. The new IE grid cell coordinates could not be placed into the same media query as the grid template definition. Doing so would lead to one of two possible outcomes. One outcome is that the default grid cell positions would override the altered positions stated in the media query. This would cause the media query to have no effect in IE. The other outcome would be for Autoprefixer to shift all of the styles inside the media query (yes, that includes all of the styles that you wrote yourself) to another location in the style sheet, potentially causing horrific CSS specificity issues. You can learn more about the thinking behind this decision in the now closed GitHub issue for it.

Autoprefixer still can’t save you from everything

Even Superman can’t always save everyone and Autoprefixer is no different. While Autoprefixer is able to cut down on a lot of the workload involved in making our grids IE-compatible, it can’t fix everything. It can only translate things that IE can understand. These are the many critical things that you need to be aware of if you don’t want to open the site up in IE one day and have it blow up in your face.

Grid Gap has limited support

As you may have seen in that last example, grid-gap isn’t currently able to be inherited through media queries. If you want to use grid-gap, you will need to duplicate the grid-gap setting across all of the media queries where you define a grid template for that grid. There is an issue open on GitHub about this. Go give it a thumbs up if you want Autoprefixer to support it. Hopefully the issue is fixed soon.

That isn’t the only problem around using grid-gap though. It is only supported by Autoprefixer when both grid-template-areas and grid-template-columns have been defined.

Autoprefixer adds grid-gap support by using grid-template-areas to understand what your grid looks like. It then takes your grid-template-columns and grid-template-rows definitions and injects the grid-gap value between each row and column, creating extra rows and columns in IE.

If you try to use grid-gap on its own without grid-template-areas, Autoprefixer has no way of knowing what cell belongs to what grid. Without that critical knowledge, it cannot safely inject the extra columns and rows that IE needs.

That explains grid-template-areas but why do we also need to define grid-template-columns? Shouldn’t something like this be just as easy for Autoprefixer to translate?

.grid { display: grid; grid-gap: 20px; grid-template-areas: "a b c" "d e f";
} .cell-a { grid-area: a;
} .cell-f { grid-area: f;
}

Rows and columns in CSS grid default to a value of auto so can’t Autoprefixer just add something like -ms-grid-columns: auto 20px auto 20px auto;? It does that for rows, so why can’t it do the same thing for columns?

Well my inquisitive friend, I explained in Part 1 that auto in IE acts a bit differently to auto in modern browsers. When columns are set to auto in IE, they will always shrink down to the value of max-content. Modern grid columns, on the other hand, will expand to 1fr if there are no other fr units being used in that grid template declaration. This discrepancy can cause a massive difference in appearance between the modern and the IE version of a grid. The Autoprefixer team felt that it was too dangerous to make assumptions about this, so they made grid-template-columns a mandatory setting in order for grid-gap to take effect.

So that explains why Autoprefixer doesn’t support grid-gap when grid-template-columns is missing. If auto behaves so differently in IE, then why does Autoprefixer support grid-gap without the user explicitly having to define grid-template-rows? Isn’t that just as bad?

Not really. When you set display: grid; on something, it’s width will grow to the full width of its container. Its height, on the other hand, typically shrinks to the height of its content. Of course this isn’t always the case. There are a number of reasons why a grid might be taller than its content. If the grid is also a flex item and the flex container is taller than the grid, then that would be one reason why the grid might be taller than its content. In general though, if there are no other forces involved, then a grid container will always be the same height as its content.

Since the height of a typical grid is the same height as its content, in most cases, auto in both IE and modern browsers will behave identically to one another. It will only differ in functionality if the height of the grid exceeds the height of the content inside of it. For the best balance between user convenience and browser consistency, the Autoprefixer team made a choice. They decided that supporting a missing grid-template-rows property but not a missing grid-template-columns property was the best way to handle grid-gap support.

No auto-placement! No auto-placement! No auto-placement!

I really can’t say this enough. The most important thing to remember when using CSS grid in IE is that everything must be placed manually. The instant you start thinking about using auto-placement is the instant your site blows up in IE. I have a method for dealing with grids that have an unknown number of cells in them. I’m covering that in Part 3 of this series. The main thing to know right now is that if you want to use CSS grid in an IE-friendly way, you should only ever use it if there are a known number of cells for a known number of rows and columns.

It’s this lack of auto-placement in IE that makes having access to grid areas through Autoprefixer such a blessing. Instead of having to calculate all of the coordinates manually, you can instead name each cell and then let Autoprefixer do the math for you. When using media queries, you only need to redefine the grid template and autoprefixer will recalculate all of the coordinates for you. You rarely have to do any column or row counting. It’s great!

Area names must be unique

The ability to use grid-template-areas is one of Autoprefixer’s greatest strengths, though it has its limits. Autoprefixer does not have any access to the issue open on GitHub that you can add your support to. In the meantime, the easiest way to ensure that each area name is unique is probably adopting a BEM style approach to naming the areas.

.grid-alpha { grid-template-areas: "grid-alpha__delta grid-alpha__echo";
} .grid-beta { grid-template-areas: "grid-beta__echo grid-beta__delta";
} .grid-cell { /* No more conflict 🙂 */ -ms-grid-column: 2; grid-area: grid-alpha__echo;
}

This can be pretty verbose if there are lots of columns and rows. You might want to shorten it down to an abbreviation instead. Of course, the less verbose your area names, the more chance there is of a conflict.

.grid-alpha { grid-template-areas: "ga_delta ga_echo";
} .grid-beta { grid-template-areas: "gb_echo gb_delta";
} .grid-cell { -ms-grid-column: 2; arid-area: ga_echo;
}

There is one major exception. Grid areas in media queries are allowed to be duplicates of other areas as long as the area names defined in the media query are targeted at the same element. Without this exception, it would be impossible to change the grid areas based on screen size. The main thing to remember is that each grid has to have its own set of unique area names that must not be shared with any other grids.

@media (min-width: 600px) { .grid-one { grid-template-areas: "alpha bravo" "alpha charlie"; }
} @media (min-width: 900px) { .grid-one { /* This is fine */ /* It is targeting the same element */ grid-template-areas: "alpha bravo charlie"; }
} @media (min-width: 900px) { /* NOT FINE! */ /* The "alpha" area is being reused on a different element! */ .grid-two { grid-template-areas: "alpha delta"; }
}

Autoprefixer has limited column and row spanning support

There are only two properties in IE’s implementation of CSS grid that will help you span multiple columns. The main one being -ms-grid-column/row-span which tells IE how many columns/rows to span. The other being -ms-grid-column/row which tells IE where to start counting from.

.grid-cell { -ms-grid-column-span: 2; /* number of cells to span */ -ms-grid-column: 1; /* starting cell */
}

In modern browsers, you have access to far more options.

Autoprefixer friendly

Out of the modern ways to span multiple cells, Autoprefixer fully supports the following. Feel free to use any of these methods as much as you like:

Specify a starting line and the number of lines to span (similar to IE):

.grid-cell { grid-column: 1 / span 2;
}

Specify an end line, then span backwards:

.grid-cell { grid-column: span 2 / 3;
}

Specify a starting line and an end line directly:

.grid-cell { grid-column: 1 / 3;
}

Specify only a number of cells to span using grid-column/row-end. Remember that IE can’t do auto-placement though. A starting line will still need to be specified elsewhere in the style sheet:

.grid-cell { /* Make sure you specify a starting line elsewhere */ grid-column-end: span 2;
}

Specify only a starting line:

.grid-cell { /* The short way */ grid-column: 1; /* The more verbose way */ grid-column-start: 1;
}
Autoprefixer unfriendly. Here be dragons!

Now this is where Autoprefixer reaches its limit. The following methods are supported in modern browsers but are not supported by Autoprefixer. This is mainly due to Autoprefixer having no idea what grid the grid cell belongs to since it can only base its decisions on what is in the stylesheet.

Specify a starting line and how many lines from the end of the explicit grid to span:

.grid-cell { grid-column: 1 / -1;
}

Specify both the start and end line from the end of the explicit grid:

.grid-cell { grid-column: -3 / -1;
}

Specify only how many lines to span using the shorthand syntax (issue in GitHub):

.grid-cell { grid-column: span 2;
}

Specify only a backwards span (IE can’t span backwards):

.grid-cell { grid-column-start: span 2;
}

Specify only an end line (IE doesn’t understand end and Autoprefixer doesn’t know where the start is):

.grid-cell { grid-column-end: 3;
}

So, basically avoid counting backwards from the end of the grid and you’ll be fine. 😊

Avoid using line names for now

One of the cool features of modern grids is giving grid templates line names. Instead of using numbers to reference a line, you can give the line a name and reference that instead. Since Autoprefixer supports grid areas, you would think that they would also support line names. Unfortunately, that isn’t the case. As of version 8.6.4, Autoprefixer does not support line names (at the time of writing). Don’t worry though! It’s not that it is impossible to support (at least not entirely), it just hasn’t been a high priority for them. If you love using line names in your grids then let them know about it in the GitHub issue for it. Post your use cases and it will surely increase the priority of the feature. In the meantime, see if you can use grid areas instead for now.

Keep in mind that, if it is going to be implemented, then every line name across your stylesheet would need to be unique. Like with grid areas, Autoprefixer wouldn’t know what line name belongs to what grid. The only way it can tell is if every line name in the stylesheet is unique (excluding media queries).

You still need to test!

IE will behave itself most of the time as long as you follow all of the rules we’ve covered so far. That said, IE can still be a bit unpredictable. Just recently, I made a grid item a vertical flowing flex container and encountered an odd bug in IE11. The column width was set to minmax(min-content, 350px) but IE seemed to treat min-content like max-content in this circumstance. This completely broke the layout. Changing it to minmax(0, 350px) fixed the issue. Just goes to show that IE’s grid implementation isn’t quite perfect.

There are also times when you might accidentally forget to explicitly place grid cells. We build our grids in modern browsers because they have the nice grid development tools (especially Firefox). Modern browsers have auto-placement, though. This means that you might be halfway through building your grid then get called away for a moment. When you return to your desk, you see the layout looking beautiful in your browser, but you completely forget that you haven’t explicitly placed any grid cells yet. You move onto the next thing, blissfully unaware that you have left IE in a completely broken state.

Neither of those issues will reveal themselves until you test your site in IE11. Any time that you get a grid looking good in a modern browser, open it up in IE and double-check that it still looks the way you expect it to.

Autoprefixer control comments

Despite Autoprefixer’s best efforts, there are still some rare occasions when it seems like Autoprefixer is hindering you more than it is helping you. If you ever find yourself in a situation where it would be easier to not have Autoprefixer translating your code, you can turn Autoprefixer off using something called a “control comment.”

autoprefixer: off

This control comment will turn off Autoprefixer translations for the entire CSS block. It will not prefix any styles before or after the point where the comment is made.

/* Input CSS */ .normal-behavior { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
} .off-behavior { display: grid; /* autoprefixer: off */ grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
} .normal-behavior-again { display: grid;
}
/* Output CSS */ .normal-behavior { display: -ms-grid; display: grid; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr; -ms-grid-rows: 1fr 1fr; grid-template-rows: 1fr 1fr;
} .off-behavior { display: grid; /* autoprefixer: off */ grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
} .normal-behavior-again { display: -ms-grid; display: grid;
}

autoprefixer: ignore next

If you are after more of a scalpel than a sledge hammer, the /* autoprefixer: ignore next */ control comment is more for you. “Ignore next” will skip the next CSS declaration rather than ignoring the entire CSS block.

/* Input CSS */ .normal-behavior { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
} .ignore-next-behavior { display: grid; /* autoprefixer: ignore next */ grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
}
/* Output CSS */ .normal-behavior { display: -ms-grid; display: grid; -ms-grid-columns: 1fr 1fr; grid-template-columns: 1fr 1fr; -ms-grid-rows: 1fr 1fr; grid-template-rows: 1fr 1fr;
} .ignore-next-behavior { display: -ms-grid; display: grid; /* autoprefixer: ignore next */ grid-template-columns: 1fr 1fr; -ms-grid-rows: 1fr 1fr; grid-template-rows: 1fr 1fr;
}

Pre-processor comments

If you are using Sass (or another CSS pre-processor) in your project, do not use the double slash (//) method for writing these comments. Sass will strip those comments out before Autoprefixer has a chance to translate the code.

/* Input SCSS */ .normal-behavior { display: grid;
} .failed-off-behavior { // autoprefixer: off display: grid;
} .successful-off-behavior { /* autoprefixer: off */ display: grid;
}
/* Output CSS */ .normal-behavior { display: -ms-grid; display: grid;
} .failed-off-behavior { display: -ms-grid; display: grid;
} .successful-off-behavior { /* autoprefixer: off */ display: grid;
}

Let’s recap!

So, after all that, here is the list of all the things you need to remember to be an IE11 CSS grid master:

  • Use the latest version of Autoprefixer (npm i autoprefixer@latest -D).
  • Turn on the Autoprefixer grid setting.
  • Do not attempt to use auto-placement, every cell must be placed manually.
  • Use grid-template-areas as your primary method for placing grid cells into position.
  • Use grid-template (not grid) as a shortcut.
  • Don’t use duplicate area names unless they are inside a media query targeting the same element. Also, give this GitHub issue your support if you would like Autoprefixer to warn you when you have used a duplicate area name.
  • You can use grid-gap as long as you define both grid-template-areas and grid-template-columns.
  • grid-gap is currently not inherited through media queries. Go give this GitHub issue a thumbs up if you want to write less grid-gap code.
  • When spanning multiple columns and rows, avoid counting backwards from the end of the grid. Autoprefixer doesn’t understand your grids well enough to supports this.
  • Avoid using line names for now. Give this GitHub issue a thumbs up if you want to start using them.
  • Use control comments /* autoprefixer: off */ and /* autoprefixer: ignore next */ to prevent Autoprefixer from translating certain parts of your style-sheet that are causing problems.
  • Don’t forget to test!

…and from Part 1:

  • IE does have an implicit grid.
  • IE supports repeat functionality.
  • minmax(), min-content and max-content are all natively supported.
  • fit-content() isn’t natively supported but you can work around this with auto and max-width settings.
  • IE auto is not equal to auto in modern browsers.

If you have any questions, or if this really helped you out, let me know in the comments! I’m also @Daniel_Tonon on Twitter. 😁

Up next…

In Part 3, I will be covering how to make a fully responsive flexbox-based grid in IE11. This flexbox technique even replicates grid-gap functionality!

Article Series:

  1. Debunking Common IE Grid Misconceptions
  2. CSS Grid and the new Autoprefixer (This Post)
  3. Faking an auto-placement grid with gaps

The post CSS Grid in IE: CSS Grid and the New Autoprefixer appeared first on CSS-Tricks.

Grid Level 2 and Subgrid

I find the concept of subgrid a little hard to wrap my mind around.

I do understand the idea that we want to use nested semantic markup as we like and have elements participate in one grid so we don’t have to flatten our markup just for layout reasons. But that is largely handled by display: contents;.

Rachel Andrew explains it in a way that finally clicked for me:

I have an item spanning three column tracks of the grid, it is also a Grid Container with three column tracks – however these do not line up with the tracks of the parent…

If the nested grid columns were to be defined as a subgrid, we would use the subgrid value of grid-template-columns on that child element. The child would then use the three column tracks that it spanned, and its children would lay out on those tracks.

It’s not that the parent disappears, it’s that it shares grid lines with the parent so that getting internal elements to line up with everything else happens naturally.

Direct Link to Article — Permalink

The post Grid Level 2 and Subgrid appeared first on CSS-Tricks.

CSS Grid Layout Module Level 2

The second iteration of CSS Grid is already in the works and the public editor’s draft was released last week! While it is by no means the final W3C recommendation, this draft is the start of discussions around big concepts many of us have been wanting to see since the first level was released, including subgrids:

In some cases it might be necessary for the contents of multiple grid items to align to each other. A grid container that is itself a grid item can defer the definition of its rows and columns to its parent grid container, making it a subgrid. In this case, the grid items of the subgrid participate in sizing the grid of the parent grid container, allowing the contents of both grids to align.

The currently defined characters of subgrid items are particularly interesting because they illustrate the differences between a subgrid and its parent grid. For example:

The subgrid is always stretched in both dimensions in its subgridded dimension(s): the align-self/justify-self properties on it are ignored, as are any specified width/height constraints.

In addition to subgrids, aspect-ratio-controlled gutters and conformance are also defined in the draft and worth a read. It’s great to see so much momentum around grids!

Direct Link to Article — Permalink


CSS Grid Layout Module Level 2 is a post from CSS-Tricks