Repository: postcss/autoprefixer (js)

Issue:
Grid Column / Row Span for IE11
The autoprefixer has slight problems with changing the column widths. 

Example a grid with three columns. In the first breakpoint, an element has 2 columns. 

```scss
grid-gap: 10px 20px;
grid-template:
  "log met qu2" 20px
  "log lin lin" auto
  "log nav nav" auto /
  200px 1fr 110px;
```

In the next breakpoint, the element `nav` should now work on a column.

```scss
grid-gap: 10px 50px;
grid-template:
  "log met soc" 20px
  "log lin lin" auto
  "log nav qu2" auto /
  290px 1fr 110px;
```

The problem here is that in the second grid I have `-ms-grid-column-span: 3` still from the previous breakpoint. Which means that the elements now overlap. I have now helped me manually add `-ms-grid-column-span: 1` at the breakpoint.

To automate the whole thing, the autoprefixer should always note `-ms-grid-column-span`, even if the box is only one column wide to overwrite old values in CSS. This also applies to the `-ms-grid-row-span`.

Pull request:
[grid-template] fix adding grid span for IE (fixes #1084)
This PR fixes #1084.

@Dan503 Can you please review grid-template.out.css in you spare time? I think now it should add -ms-grid-(row|column)-span just fine 👍 

Patch:
diff --git a/lib/hacks/grid-utils.js b/lib/hacks/grid-utils.js
index e959faa..8b54381 100644
--- a/lib/hacks/grid-utils.js
+++ b/lib/hacks/grid-utils.js
@@ -345,13 +345,20 @@ function parseTemplate ({
 
 // Insert parsed grid areas
 
-function getMSDecls (area) {
+/**
+ * Get an array of -ms- prefixed props and values
+ * @param  {Object} [area] area object with columm and row data
+ * @param  {Boolean} [addRowSpan] should we add grid-column-row value?
+ * @param  {Boolean} [addColumnSpan] should we add grid-column-span value?
+ * @return {Array<Object>}
+ */
+function getMSDecls (area, addRowSpan = false, addColumnSpan = false) {
   return [].concat(
     {
       prop: '-ms-grid-row',
       value: String(area.row.start)
     },
-    area.row.span > 1 ? {
+    (area.row.span > 1 || addRowSpan) ? {
       prop: '-ms-grid-row-span',
       value: String(area.row.span)
     } : [],
@@ -359,7 +366,7 @@ function getMSDecls (area) {
       prop: '-ms-grid-column',
       value: String(area.column.start)
     },
-    area.column.span > 1 ? {
+    (area.column.span > 1 || addColumnSpan) ? {
       prop: '-ms-grid-column-span',
       value: String(area.column.span)
     } : []
@@ -375,6 +382,44 @@ function getParentMedia (parent) {
   return getParentMedia(parent.parent)
 }
 
+/**
+ * Check grid-template(-areas) rules with the same selector for
+ * -ms-grid-(row|column)-span values. If initial and compared values are
+ * different - return an array of boolean values which need to be updated
+ * @param  {Declaration} decl
+ * @param  {Object} area area object with column and row data
+ * @param  {String} areaName area name (e.g. "head")
+ * @return {Array<Boolean, Boolean>}
+ */
+function shouldAddSpan (decl, area, areaName) {
+  const root = decl.root()
+  const rule = decl.parent
+  const overrideValues = [false, false]
+
+  root.walkRules(rule.selector, node => {
+    // abort if we are on the same rule
+    if (rule.toString() === node.toString()) {
+      return false
+    }
+
+    node.walkDecls('grid-template', d => {
+      const template = parseTemplate({ decl: d, gap: getGridGap(d) })
+      const comparedArea = template.areas[areaName]
+      if (area.row.span !== comparedArea.row.span) {
+        overrideValues[0] = true
+      } else if (area.column.span !== comparedArea.column.span) {
+        overrideValues[1] = true
+      }
+
+      return undefined
+    })
+
+    return undefined
+  })
+
+  return overrideValues
+}
+
 function insertAreas (areas, decl, result) {
   let missed = Object.keys(areas)
 
@@ -397,7 +442,8 @@ function insertAreas (areas, decl, result) {
       rule.removeAll()
 
       // insert prefixed decls in new rule
-      getMSDecls(area)
+      const [addRowSpan, addColumnSpan] = shouldAddSpan(decl, area, value)
+      getMSDecls(area, addRowSpan, addColumnSpan)
         .forEach(i => rule.append(
           Object.assign(i, {
             raws: {


Test patch:
diff --git a/test/cases/grid-template.out.css b/test/cases/grid-template.out.css
index 3260401..ace8dff 100644
--- a/test/cases/grid-template.out.css
+++ b/test/cases/grid-template.out.css
@@ -87,9 +87,11 @@
     .head {
         -ms-grid-row: 1;
         -ms-grid-column: 1;
+        -ms-grid-column-span: 1;
     }
     .nav {
         -ms-grid-row: 2;
+        -ms-grid-row-span: 1;
         -ms-grid-column: 1;
     }
     .main {
@@ -389,11 +391,13 @@
 @media (min-width: 600px) {
   .k-1 {
         -ms-grid-row: 1;
+        -ms-grid-row-span: 1;
         -ms-grid-column: 1;
   }
   .k-2 {
         -ms-grid-row: 1;
         -ms-grid-column: 3;
+        -ms-grid-column-span: 1;
   }
 }