Repository: postcss/autoprefixer
Pull request #1057 (2018-06-07 11:27:07)

[css-grid] move media query cell placements to come after cell styles
Third solution without duplication media queries.

Now we have solutions for all [3 decisions](https://github.com/postcss/autoprefixer/issues/1048#issuecomment-390410054) that we discussed 😄 

ai: Oh 😅

I prefer to duplicate medias. It is more stable for the cases (like 2-3 different media).
yepninja: [Here](https://github.com/postcss/autoprefixer/issues/1048) we decided to implement the solution without duplications.
ai: Since people afraid of Autoprefixer’s Grids, I think using safest way with a few extra media will be better to promotion.

They will be compressed by gzip and we need max safety.

cc @Dan503
Dan503: We agreed to do a half/half approach remember?

We don't want to shift author styles around in the declaration order. The goal is to create a single duplicate media query that holds all of the autoprefixer generated area code in it that is placed after the last grid area reference.

See my original example in the issue to see what I mean.

Creating a duplicate query for each area reference creates far too much code bloat and moving the full original media query is extremely dangerous.
Dan503: Option 2 is the method I'm talking about. That is the one we agreed to.
ai: @Dan503 but creating a single media for every area seems dangerous for me as well. Code bloat will be fixed by gzip. Are you sure that it is a good reason to not use the safest way?
Dan503: It's not every single one.

Take a good look at the example code I posted in the issue.

Notice that there is only one duplicate media query. There is not a duplicate for each declaration.

There is basically a duplicate query per media query per grid. It is not a duplicate query per query per area.
ai: > There is basically a duplicate query per media query per grid. It is not a duplicate query per query per area.

Yeap I got it. And I am afraid that combining different areas (which could be in different place of CSS file) into a that second media query is not safe, since we move areas declaration to a different position.
Dan503: Yes I know, Autoprefixer can't handle grids sharing the same area names. It has that restriction hard boiled into it's area code which is why I opened issue https://github.com/postcss/autoprefixer/issues/1038

I point this restriction out in the article and explain why it is the case so you won't need to worry about community backlash

Patch:
diff --git a/lib/hacks/grid-utils.js b/lib/hacks/grid-utils.js
index e380e8e..98bd8ef 100644
--- a/lib/hacks/grid-utils.js
+++ b/lib/hacks/grid-utils.js
@@ -296,6 +296,9 @@ function insertAreas(areas, decl, result) {
     let missed = Object.keys(areas);
 
     const parentMedia = getParentMedia(decl.parent);
+    const rules = [];
+    const areasLength = Object.keys(areas).length;
+    let areasCount = 0;
 
     decl.root().walkDecls('grid-area', gridArea => {
 
@@ -306,13 +309,6 @@ function insertAreas(areas, decl, result) {
 
         if (area && parentMedia) {
 
-            // skip if grid-template-areas already prefixed in media
-            if (parentMedia.some(
-                i => i.selector === gridArea.parent.selector
-            )) {
-                return undefined;
-            }
-
             // create new rule
             const rule = decl.parent.clone({
                 selector: gridArea.parent.selector
@@ -329,8 +325,23 @@ function insertAreas(areas, decl, result) {
                     })
                 ));
 
-            // insert new rule with prefixed decl to existing media
-            parentMedia.append(rule);
+            rules.push(rule);
+            areasCount++;
+            if (areasCount === areasLength) {
+                const next = gridArea.parent.next();
+
+                if (
+                    next.type === 'atrule' &&
+                    next.name === 'media' &&
+                    next.params === parentMedia.params &&
+                    next.first.type === 'rule' &&
+                    next.first.selector && parentMedia.first.selector &&
+                    /^-ms-/.test(next.first.first.prop)
+                ) return undefined;
+
+                const areaMedia = parentMedia.clone().removeAll().append(rules);
+                gridArea.parent.after(areaMedia);
+            }
 
             return undefined;
         }


Test patch:
diff --git a/test/cases/grid-template-areas.css b/test/cases/grid-template-areas.css
index a42c034..3a2a095 100644
--- a/test/cases/grid-template-areas.css
+++ b/test/cases/grid-template-areas.css
@@ -6,6 +6,12 @@
         "another";
 }
 
+@media (max-width: 1000px) {
+    .a {
+        grid-template-areas: "head main";
+    }
+}
+
 .b {
     grid-area: head;
 }
@@ -21,9 +27,3 @@
 .e {
     grid-area: foot;
 }
-
-@media (max-width: 1000px) {
-    .a {
-        grid-template-areas: "head main";
-    }
-}
diff --git a/test/cases/grid-template-areas.out.css b/test/cases/grid-template-areas.out.css
index 8b43bf9..fc28052 100644
--- a/test/cases/grid-template-areas.out.css
+++ b/test/cases/grid-template-areas.out.css
@@ -6,6 +6,12 @@
         "another";
 }
 
+@media (max-width: 1000px) {
+    .a {
+        grid-template-areas: "head main";
+    }
+}
+
 .b {
     -ms-grid-row: 1;
     -ms-grid-column: 1;
@@ -19,6 +25,17 @@
     grid-area: main;
 }
 
+@media (max-width: 1000px) {
+    .b {
+        -ms-grid-row: 1;
+        -ms-grid-column: 1;
+    }
+    .c {
+        -ms-grid-row: 1;
+        -ms-grid-column: 2;
+    }
+}
+
 .d {
     -ms-grid-row: 2;
     -ms-grid-row-span: 2;
@@ -31,17 +48,3 @@
     -ms-grid-column: 2;
     grid-area: foot;
 }
-
-@media (max-width: 1000px) {
-    .a {
-        grid-template-areas: "head main";
-    }
-    .b {
-        -ms-grid-row: 1;
-        -ms-grid-column: 1;
-    }
-    .c {
-        -ms-grid-row: 1;
-        -ms-grid-column: 2;
-    }
-}
diff --git a/test/cases/grid-template.css b/test/cases/grid-template.css
index ce32b84..cde99c6 100644
--- a/test/cases/grid-template.css
+++ b/test/cases/grid-template.css
@@ -10,6 +10,17 @@
         / 120px repeat(4, 250px 10px);
 }
 
+@media (min-width: 1000px) {
+    .b {
+        grid-template:
+            [header-left] "head" 30px [header-right]
+            [nav-left]    "nav"  auto  [nav-right]
+            [main-left]   "main" 1fr  [main-right]
+            [footer-left] "foot" 30px [footer-right]
+            / 1fr;
+    }
+}
+
 .c {
     grid-template:
         "hd hd hd hd hd hd hd hd hd" minmax(100px, auto)
@@ -65,14 +76,3 @@
 .ft {
     grid-area: ft;
 }
-
-@media (min-width: 1000px) {
-    .b {
-        grid-template:
-            [header-left] "head" 30px [header-right]
-            [nav-left]    "nav"  auto  [nav-right]
-            [main-left]   "main" 1fr  [main-right]
-            [footer-left] "foot" 30px [footer-right]
-            / 1fr;
-    }
-}
diff --git a/test/cases/grid-template.out.css b/test/cases/grid-template.out.css
index cbb7d3c..e634283 100644
--- a/test/cases/grid-template.out.css
+++ b/test/cases/grid-template.out.css
@@ -14,6 +14,19 @@
         / 120px repeat(4, 250px 10px);
 }
 
+@media (min-width: 1000px) {
+    .b {
+        -ms-grid-rows: 30px auto 1fr 30px;
+        -ms-grid-columns: 1fr;
+        grid-template:
+            [header-left] "head" 30px [header-right]
+            [nav-left]    "nav"  auto  [nav-right]
+            [main-left]   "main" 1fr  [main-right]
+            [footer-left] "foot" 30px [footer-right]
+            / 1fr;
+    }
+}
+
 .c {
     -ms-grid-rows: minmax(100px, auto) minmax(100px, auto) minmax(100px, auto);
     -ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
@@ -70,6 +83,25 @@
     grid-area: foot;
 }
 
+@media (min-width: 1000px) {
+    .head {
+        -ms-grid-row: 1;
+        -ms-grid-column: 1;
+    }
+    .nav {
+        -ms-grid-row: 2;
+        -ms-grid-column: 1;
+    }
+    .main {
+        -ms-grid-row: 3;
+        -ms-grid-column: 1;
+    }
+    .foot {
+        -ms-grid-row: 4;
+        -ms-grid-column: 1;
+    }
+}
+
 .hd {
     -ms-grid-row: 1;
     -ms-grid-column: 1;
@@ -97,32 +129,3 @@
     -ms-grid-column-span: 9;
     grid-area: ft;
 }
-
-@media (min-width: 1000px) {
-    .b {
-        -ms-grid-rows: 30px auto 1fr 30px;
-        -ms-grid-columns: 1fr;
-        grid-template:
-            [header-left] "head" 30px [header-right]
-            [nav-left]    "nav"  auto  [nav-right]
-            [main-left]   "main" 1fr  [main-right]
-            [footer-left] "foot" 30px [footer-right]
-            / 1fr;
-    }
-    .head {
-        -ms-grid-row: 1;
-        -ms-grid-column: 1;
-    }
-    .nav {
-        -ms-grid-row: 2;
-        -ms-grid-column: 1;
-    }
-    .main {
-        -ms-grid-row: 3;
-        -ms-grid-column: 1;
-    }
-    .foot {
-        -ms-grid-row: 4;
-        -ms-grid-column: 1;
-    }
-}