[CSS Grid Layout] Grid item's auto-margins are not applied correctly
authorjfernandez@igalia.com <jfernandez@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Jul 2015 17:53:55 +0000 (17:53 +0000)
committerjfernandez@igalia.com <jfernandez@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 Jul 2015 17:53:55 +0000 (17:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146581

Reviewed by Darin Adler.

Source/WebCore:

Grid Layout specification states that auto-margins must prevent to apply
any Box Alignment property in that dimension. Instead, auto-margin is
applied as described in the spec.

http://dev.w3.org/csswg/css-grid/#auto-margins

Only Flexbox and Grid Layout implement vertical auto-margin alignment;
for other layout modes, auto-margin should compute as 0.

Tests: fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html
       fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html
       fast/css-grid-layout/grid-item-auto-margins-alignment.html

* rendering/RenderBox.cpp:
(WebCore::RenderBox::styleDidChange):
(WebCore::RenderBox::updateGridAlignmentAfterStyleChange):
* rendering/RenderBox.h:
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::layoutGridItems):
(WebCore::RenderGrid::hasAutoMarginsInColumnAxis):
(WebCore::RenderGrid::hasAutoMarginsInRowAxis):
(WebCore::RenderGrid::updateAutoMarginsInColumnAxisIfNeeded):
(WebCore::RenderGrid::rowPositionForChild):
(WebCore::RenderGrid::columnPositionForChild):
* rendering/RenderGrid.h:

LayoutTests:

Tests to verify auto-margins alignment works as expected with grid items.

* fast/css-grid-layout/grid-item-auto-margins-alignment-expected.txt: Added.
* fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr-expected.txt: Added.
* fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html: Added.
* fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl-expected.txt: Added.
* fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html: Added.
* fast/css-grid-layout/grid-item-auto-margins-alignment.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@186682 268f45cc-cd09-0410-ab3c-d52691b4dbfc

12 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl-expected.txt [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html [new file with mode: 0644]
LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderGrid.cpp
Source/WebCore/rendering/RenderGrid.h

index 558cf60..5149924 100644 (file)
@@ -1,3 +1,19 @@
+2015-07-10  Javier Fernandez  <jfernandez@igalia.com>
+
+        [CSS Grid Layout] Grid item's auto-margins are not applied correctly
+        https://bugs.webkit.org/show_bug.cgi?id=146581
+
+        Reviewed by Darin Adler.
+
+        Tests to verify auto-margins alignment works as expected with grid items.
+
+        * fast/css-grid-layout/grid-item-auto-margins-alignment-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html: Added.
+        * fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl-expected.txt: Added.
+        * fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html: Added.
+        * fast/css-grid-layout/grid-item-auto-margins-alignment.html: Added.
+
 2015-07-10  Hunseop Jeong  <hs85.jeong@samsung.com>
 
         Fix typo in LayoutTests/platform/wk2/TestExpectation.
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-expected.txt b/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-expected.txt
new file mode 100644 (file)
index 0000000..4c0dd69
--- /dev/null
@@ -0,0 +1,14 @@
+This test checks that aling-self and justify-self properties are not applied when there is auto-margin in the correponding axis. Instead, auto-margin alignment should be applied.
+
+Direction: LTR | Self Aligmment: center | 1 auto-margin
+
+PASS
+Direction: LTR | Self Aligmment: start | 4 auto-margin
+
+PASS
+Direction: RTL | Self Aligmment: center | 1 auto-margin
+
+PASS
+Direction: RTL | Self Aligmment: start | 4 auto-margin
+
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr-expected.txt b/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr-expected.txt
new file mode 100644 (file)
index 0000000..4c0dd69
--- /dev/null
@@ -0,0 +1,14 @@
+This test checks that aling-self and justify-self properties are not applied when there is auto-margin in the correponding axis. Instead, auto-margin alignment should be applied.
+
+Direction: LTR | Self Aligmment: center | 1 auto-margin
+
+PASS
+Direction: LTR | Self Aligmment: start | 4 auto-margin
+
+PASS
+Direction: RTL | Self Aligmment: center | 1 auto-margin
+
+PASS
+Direction: RTL | Self Aligmment: start | 4 auto-margin
+
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html b/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html
new file mode 100644 (file)
index 0000000..a6a36b7
--- /dev/null
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link href="resources/grid.css" rel="stylesheet">
+<script src="../../resources/check-layout.js"></script>
+<style>
+body {
+    margin: 0;
+}
+
+.grid {
+    -webkit-grid-template-columns: 100px 100px;
+    -webkit-grid-template-rows: 200px 200px;
+    width: -webkit-fit-content;
+    margin-bottom: 20px;
+}
+
+.cell {
+    width: 20px;
+    height: 40px;
+}
+
+.item {
+    width: 8px;
+    height: 16px;
+    background: black;
+}
+
+.autoMarginTop { margin-top: auto; }
+.autoMarginRight { margin-right: auto; }
+.autoMarginBottom { margin-bottom: auto; }
+.autoMarginLeft { margin-left: auto; }
+.autoMargin { margin: auto; }
+
+.itemsCenter {
+    align-items: center;
+    justify-items: center;
+}
+</style>
+</head>
+<body onload="checkLayout('.grid')">
+
+<p>This test checks that aling-self and justify-self properties are not applied when there is auto-margin in the correponding axis. Instead, auto-margin alignment should be applied.</p>
+
+<p>Direction: LTR | Self Aligmment: center | 1 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalLR itemsCenter" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMarginTop firstRowFirstColumn" data-offset-x="90" data-offset-y="60" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginRight firstRowSecondColumn" data-offset-x="0" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginLeft secondRowFirstColumn" data-offset-x="380" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginBottom secondRowSecondColumn" data-offset-x="290" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<p>Direction: LTR | Self Aligmment: start | 4 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalLR" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMargin firstRowFirstColumn" data-offset-x="90" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin firstRowSecondColumn" data-offset-x="90" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowFirstColumn" data-offset-x="290" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowSecondColumn" data-offset-x="290" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<!-- direction RTL -->
+<p>Direction: RTL | Self Aligmment: center | 1 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalLR itemsCenter directionRTL" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMarginTop firstRowFirstColumn" data-offset-x="90" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginRight firstRowSecondColumn" data-offset-x="0" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginLeft secondRowFirstColumn" data-offset-x="380" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginBottom secondRowSecondColumn" data-offset-x="290" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+
+<p>Direction: RTL | Self Aligmment: start | 4 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalLR directionRTL" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMargin firstRowFirstColumn" data-offset-x="90" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin firstRowSecondColumn" data-offset-x="90" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowFirstColumn" data-offset-x="290" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowSecondColumn" data-offset-x="290" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl-expected.txt b/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl-expected.txt
new file mode 100644 (file)
index 0000000..4c0dd69
--- /dev/null
@@ -0,0 +1,14 @@
+This test checks that aling-self and justify-self properties are not applied when there is auto-margin in the correponding axis. Instead, auto-margin alignment should be applied.
+
+Direction: LTR | Self Aligmment: center | 1 auto-margin
+
+PASS
+Direction: LTR | Self Aligmment: start | 4 auto-margin
+
+PASS
+Direction: RTL | Self Aligmment: center | 1 auto-margin
+
+PASS
+Direction: RTL | Self Aligmment: start | 4 auto-margin
+
+PASS
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html b/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html
new file mode 100644 (file)
index 0000000..cd03ac5
--- /dev/null
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link href="resources/grid.css" rel="stylesheet">
+<script src="../../resources/check-layout.js"></script>
+<style>
+body {
+    margin: 0;
+}
+
+.grid {
+    -webkit-grid-template-columns: 100px 100px;
+    -webkit-grid-template-rows: 200px 200px;
+    width: -webkit-fit-content;
+    margin-bottom: 20px;
+}
+
+.cell {
+    width: 20px;
+    height: 40px;
+}
+
+.item {
+    width: 8px;
+    height: 16px;
+    background: black;
+}
+
+.autoMarginTop { margin-top: auto; }
+.autoMarginRight { margin-right: auto; }
+.autoMarginBottom { margin-bottom: auto; }
+.autoMarginLeft { margin-left: auto; }
+.autoMargin { margin: auto; }
+
+.itemsCenter {
+    align-items: center;
+    justify-items: center;
+}
+</style>
+</head>
+<body onload="checkLayout('.grid')">
+
+<p>This test checks that aling-self and justify-self properties are not applied when there is auto-margin in the correponding axis. Instead, auto-margin alignment should be applied.</p>
+
+<p>Direction: LTR | Self Aligmment: center | 1 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalRL itemsCenter" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMarginTop firstRowFirstColumn" data-offset-x="290" data-offset-y="60" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginRight firstRowSecondColumn" data-offset-x="200" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginLeft secondRowFirstColumn" data-offset-x="180" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginBottom secondRowSecondColumn" data-offset-x="90" data-offset-y="100" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<p>Direction: LTR | Self Aligmment: start | 4 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalRL" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMargin firstRowFirstColumn" data-offset-x="290" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin firstRowSecondColumn" data-offset-x="290" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowFirstColumn" data-offset-x="90" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowSecondColumn" data-offset-x="90" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<!-- direction RTL -->
+<p>Direction: RTL | Self Aligmment: center | 1 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalRL itemsCenter directionRTL" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMarginTop firstRowFirstColumn" data-offset-x="290" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginRight firstRowSecondColumn" data-offset-x="200" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginLeft secondRowFirstColumn" data-offset-x="180" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginBottom secondRowSecondColumn" data-offset-x="90" data-offset-y="0" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+
+<p>Direction: RTL | Self Aligmment: start | 4 auto-margin</p>
+<div style="position: relative">
+    <div class="grid verticalRL directionRTL" data-expected-width="400" data-expected-height="200">
+        <div class="cell autoMargin firstRowFirstColumn" data-offset-x="290" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin firstRowSecondColumn" data-offset-x="290" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowFirstColumn" data-offset-x="90" data-offset-y="130" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowSecondColumn" data-offset-x="90" data-offset-y="30" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+
+</body>
+</html>
diff --git a/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment.html b/LayoutTests/fast/css-grid-layout/grid-item-auto-margins-alignment.html
new file mode 100644 (file)
index 0000000..1c386d9
--- /dev/null
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link href="resources/grid.css" rel="stylesheet">
+<script src="../../resources/check-layout.js"></script>
+<style>
+body {
+    margin: 0;
+}
+
+.grid {
+    -webkit-grid-template-columns: 100px 100px;
+    -webkit-grid-template-rows: 200px 200px;
+    width: -webkit-fit-content;
+    margin-bottom: 20px;
+}
+
+.cell {
+    width: 20px;
+    height: 40px;
+}
+
+.item {
+    width: 8px;
+    height: 16px;
+    background: black;
+}
+
+.autoMarginTop { margin-top: auto; }
+.autoMarginRight { margin-right: auto; }
+.autoMarginBottom { margin-bottom: auto; }
+.autoMarginLeft { margin-left: auto; }
+.autoMargin { margin: auto; }
+
+.itemsCenter {
+    align-items: center;
+    justify-items: center;
+}
+</style>
+</head>
+<body onload="checkLayout('.grid')">
+
+<p>This test checks that aling-self and justify-self properties are not applied when there is auto-margin in the correponding axis. Instead, auto-margin alignment should be applied.</p>
+
+<p>Direction: LTR | Self Aligmment: center | 1 auto-margin</p>
+<div style="position: relative">
+    <div class="grid itemsCenter" data-expected-width="200" data-expected-height="400">
+        <div class="cell autoMarginTop firstRowFirstColumn" data-offset-x="40" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginRight firstRowSecondColumn" data-offset-x="100" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginLeft secondRowFirstColumn" data-offset-x="80" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginBottom secondRowSecondColumn" data-offset-x="140" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<p>Direction: LTR | Self Aligmment: start | 4 auto-margin</p>
+<div style="position: relative">
+    <div class="grid" data-expected-width="200" data-expected-height="400">
+        <div class="cell autoMargin firstRowFirstColumn" data-offset-x="40" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin firstRowSecondColumn" data-offset-x="140" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowFirstColumn" data-offset-x="40" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowSecondColumn" data-offset-x="140" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+<!-- direction RTL -->
+<p>Direction: RTL | Self Aligmment: center | 1 auto-margin</p>
+<div style="position: relative">
+    <div class="grid itemsCenter directionRTL" data-expected-width="200" data-expected-height="400">
+        <div class="cell autoMarginTop firstRowFirstColumn" data-offset-x="140" data-offset-y="160" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginRight firstRowSecondColumn" data-offset-x="0" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginLeft secondRowFirstColumn" data-offset-x="180" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMarginBottom secondRowSecondColumn" data-offset-x="40" data-offset-y="200" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+
+<p>Direction: RTL | Self Aligmment: start | 4 auto-margin</p>
+<div style="position: relative">
+    <div class="grid directionRTL" data-expected-width="200" data-expected-height="400">
+        <div class="cell autoMargin firstRowFirstColumn" data-offset-x="140" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin firstRowSecondColumn" data-offset-x="40" data-offset-y="80" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowFirstColumn" data-offset-x="140" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
+        <div class="cell autoMargin secondRowSecondColumn" data-offset-x="40" data-offset-y="280" data-expected-width="20" data-expected-height="40"></div>
+    </div>
+</div>
+
+
+</body>
+</html>
index 0e71056..7cfaa98 100644 (file)
@@ -1,3 +1,36 @@
+2015-07-10  Javier Fernandez  <jfernandez@igalia.com>
+
+        [CSS Grid Layout] Grid item's auto-margins are not applied correctly
+        https://bugs.webkit.org/show_bug.cgi?id=146581
+
+        Reviewed by Darin Adler.
+
+        Grid Layout specification states that auto-margins must prevent to apply
+        any Box Alignment property in that dimension. Instead, auto-margin is
+        applied as described in the spec.
+
+        http://dev.w3.org/csswg/css-grid/#auto-margins
+
+        Only Flexbox and Grid Layout implement vertical auto-margin alignment;
+        for other layout modes, auto-margin should compute as 0.
+
+        Tests: fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-lr.html
+               fast/css-grid-layout/grid-item-auto-margins-alignment-vertical-rl.html
+               fast/css-grid-layout/grid-item-auto-margins-alignment.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::styleDidChange):
+        (WebCore::RenderBox::updateGridAlignmentAfterStyleChange):
+        * rendering/RenderBox.h:
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::layoutGridItems):
+        (WebCore::RenderGrid::hasAutoMarginsInColumnAxis):
+        (WebCore::RenderGrid::hasAutoMarginsInRowAxis):
+        (WebCore::RenderGrid::updateAutoMarginsInColumnAxisIfNeeded):
+        (WebCore::RenderGrid::rowPositionForChild):
+        (WebCore::RenderGrid::columnPositionForChild):
+        * rendering/RenderGrid.h:
+
 2015-07-10  Csaba Osztrogon√°c  <ossy@webkit.org>
 
         Fix overloaded virtual function warning in ScrollbarThemeGtk.h
index 078f903..8cd7657 100644 (file)
@@ -434,6 +434,10 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
     if ((oldStyle && oldStyle->shapeOutside()) || style().shapeOutside())
         updateShapeOutsideInfoAfterStyleChange(style(), oldStyle);
 #endif
+
+#if ENABLE(CSS_GRID_LAYOUT)
+    updateGridAlignmentAfterStyleChange(oldStyle);
+#endif
 }
 
 #if ENABLE(CSS_SHAPES)
@@ -462,6 +466,24 @@ void RenderBox::updateShapeOutsideInfoAfterStyleChange(const RenderStyle& style,
 }
 #endif
 
+#if ENABLE(CSS_GRID_LAYOUT)
+void RenderBox::updateGridAlignmentAfterStyleChange(const RenderStyle* oldStyle)
+{
+    if (!oldStyle || !parent() || !parent()->isRenderGrid())
+        return;
+
+    // auto-margin prevents alignment properties to be applied, which affects specially
+    // to the stretching logic. We must detect and handling style changes like this.
+    bool isHorizontalGrid = parent()->isHorizontalWritingMode();
+    Length topOrLeft = isHorizontalGrid ? style().marginTop() : style().marginLeft();
+    Length bottomOrRight = isHorizontalGrid ? style().marginBottom() : style().marginRight();
+    Length oldTopOrLeft = isHorizontalGrid ? oldStyle->marginTop() : oldStyle->marginLeft();
+    Length oldBottomOrRight = isHorizontalGrid ? oldStyle->marginBottom() : oldStyle->marginRight();
+    if ((!topOrLeft.isAuto() && oldTopOrLeft.isAuto()) || (!bottomOrRight.isAuto() && oldBottomOrRight.isAuto()))
+        updateLogicalHeight();
+}
+#endif
+
 void RenderBox::updateFromStyle()
 {
     RenderBoxModelObject::updateFromStyle();
index 5d47e47..e5c033b 100644 (file)
@@ -673,6 +673,7 @@ private:
 #endif
 
 #if ENABLE(CSS_GRID_LAYOUT)
+    void updateGridAlignmentAfterStyleChange(const RenderStyle*);
     bool isGridItem() const { return parent() && parent()->isRenderGrid(); }
 #endif
 
index 75e6615..6cab13e 100644 (file)
@@ -1194,6 +1194,9 @@ void RenderGrid::layoutGridItems()
 
         child->layoutIfNeeded();
 
+        // We need pending layouts to be done in order to compute auto-margins properly.
+        updateAutoMarginsInColumnAxisIfNeeded(*child, overrideContainingBlockContentLogicalHeight);
+
         child->setLogicalLocation(findChildLogicalPosition(*child));
 
         // If the child moved, we have to repaint it as well as any floating/positioned
@@ -1319,6 +1322,55 @@ void RenderGrid::applyStretchAlignmentToChildIfNeeded(RenderBox& child, LayoutUn
     }
 }
 
+// FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
+bool RenderGrid::hasAutoMarginsInColumnAxis(const RenderBox& child) const
+{
+    if (isHorizontalWritingMode())
+        return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
+    return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
+}
+
+// FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
+bool RenderGrid::hasAutoMarginsInRowAxis(const RenderBox& child) const
+{
+    if (isHorizontalWritingMode())
+        return child.style().marginLeft().isAuto() || child.style().marginRight().isAuto();
+    return child.style().marginTop().isAuto() || child.style().marginBottom().isAuto();
+}
+
+// FIXME: This logic is shared by RenderFlexibleBox, so it should be moved to RenderBox.
+void RenderGrid::updateAutoMarginsInColumnAxisIfNeeded(RenderBox& child, LayoutUnit gridAreaBreadthForChild)
+{
+    ASSERT(!child.isOutOfFlowPositioned());
+
+    LayoutUnit availableAlignmentSpace = gridAreaBreadthForChild - child.logicalHeight();
+    if (availableAlignmentSpace <= 0)
+        return;
+
+    bool isHorizontal = isHorizontalWritingMode();
+    Length topOrLeft = isHorizontal ? child.style().marginTop() : child.style().marginLeft();
+    Length bottomOrRight = isHorizontal ? child.style().marginBottom() : child.style().marginRight();
+    if (topOrLeft.isAuto() && bottomOrRight.isAuto()) {
+        if (isHorizontal) {
+            child.setMarginTop(availableAlignmentSpace / 2);
+            child.setMarginBottom(availableAlignmentSpace / 2);
+        } else {
+            child.setMarginLeft(availableAlignmentSpace / 2);
+            child.setMarginRight(availableAlignmentSpace / 2);
+        }
+    } else if (topOrLeft.isAuto()) {
+        if (isHorizontal)
+            child.setMarginTop(availableAlignmentSpace);
+        else
+            child.setMarginLeft(availableAlignmentSpace);
+    } else if (bottomOrRight.isAuto()) {
+        if (isHorizontal)
+            child.setMarginBottom(availableAlignmentSpace);
+        else
+            child.setMarginRight(availableAlignmentSpace);
+    }
+}
+
 GridAxisPosition RenderGrid::columnAxisPositionForChild(const RenderBox& child) const
 {
     bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
@@ -1414,7 +1466,8 @@ LayoutUnit RenderGrid::rowPositionForChild(const RenderBox& child) const
     const GridCoordinate& coordinate = cachedGridCoordinate(child);
     LayoutUnit startOfRow = m_rowPositions[coordinate.rows.resolvedInitialPosition.toInt()];
     LayoutUnit startPosition = startOfRow + marginBeforeForChild(child);
-
+    if (hasAutoMarginsInColumnAxis(child))
+        return startPosition;
     GridAxisPosition axisPosition = columnAxisPositionForChild(child);
     switch (axisPosition) {
     case GridAxisStart:
@@ -1437,7 +1490,8 @@ LayoutUnit RenderGrid::columnPositionForChild(const RenderBox& child) const
     const GridCoordinate& coordinate = cachedGridCoordinate(child);
     LayoutUnit startOfColumn = m_columnPositions[coordinate.columns.resolvedInitialPosition.toInt()];
     LayoutUnit startPosition = startOfColumn + marginStartForChild(child);
-
+    if (hasAutoMarginsInRowAxis(child))
+        return startPosition;
     GridAxisPosition axisPosition = rowAxisPositionForChild(child);
     switch (axisPosition) {
     case GridAxisStart:
index b5cce4a..c3bda56 100644 (file)
@@ -136,6 +136,9 @@ private:
     LayoutUnit computeMarginLogicalHeightForChild(const RenderBox&) const;
     LayoutUnit availableAlignmentSpaceForChildBeforeStretching(LayoutUnit gridAreaBreadthForChild, const RenderBox&) const;
     void applyStretchAlignmentToChildIfNeeded(RenderBox&, LayoutUnit gridAreaBreadthForChild);
+    bool hasAutoMarginsInColumnAxis(const RenderBox&) const;
+    bool hasAutoMarginsInRowAxis(const RenderBox&) const;
+    void updateAutoMarginsInColumnAxisIfNeeded(RenderBox&, LayoutUnit gridAreaBreadthForChild);
 
 #ifndef NDEBUG
     bool tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection, const Vector<GridTrack>&);