Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
[CSS Grid Layout] Fix positioning grid items using named grid lines/a…
…reas https://bugs.webkit.org/show_bug.cgi?id=129372 Reviewed by Darin Adler. Source/WebCore: Our code was assuming that a <custom-ident> in -webkit-grid-{column|row}-{start|end} and -webkit-grid-{column|row} was always a grid area name. That's wrong because the <custom-ident> could be also a explicitly named grid line or the an implicitly named grid line created by a grid area definition. The style resolution code was not correct either. This patch fixes it so it now matches the spec, which means that: - first we try to match any existing grid area. - then if there is a named grid line with the name <custom-ident>-{start|end} for -webkit-grid-{column|row}-{start|end} defined before the grid area then we use it instead of the grid area. - otherwise if there is a named grid line we resolve to the first such line. - otherwise we treat it as 'auto'. Fixing this uncovered a bug in GridPosition, we were not using the name of the stored grid area to check if two GridPositions were the same. Tests: fast/css-grid-layout/grid-item-position-changed-dynamic.html fast/css-grid-layout/named-grid-lines-with-named-grid-areas-resolution.html * css/StyleResolver.cpp: (WebCore::gridLineDefinedBeforeGridArea): New function to check if a given named grid line was defined before an implicit named grid line created by a grid area definition. (WebCore::StyleResolver::adjustNamedGridItemPosition): New function that adjusts the position of a GridPosition parsed as a grid area. (WebCore::StyleResolver::adjustGridItemPosition): Use the new function adjustNamedGridItemPosition to adjust the positions of named grid lines. * css/StyleResolver.h: * rendering/RenderGrid.cpp: (WebCore::RenderGrid::resolveNamedGridLinePositionFromStyle): Use GridPosition:: namespace. (WebCore::RenderGrid::resolveGridPositionFromStyle): Ditto. (WebCore::RenderGrid::resolveRowEndColumnEndNamedGridLinePositionAgainstOppositePosition): Ditto. * rendering/RenderGrid.h: * rendering/style/GridPosition.h: (WebCore::GridPosition::adjustGridPositionForRowEndColumnEndSide): Moved from RenderGrid.cpp. (WebCore::GridPosition::adjustGridPositionForSide): Ditto. (WebCore::GridPosition::operator==): Use the named grid line to check equality. LayoutTests: Added a new test that checks that we correctly position grid items using named grid lines, grid areas and also with the implicit named grid lines created by grid areas. I'm also importing a test from Blink that checks that we can dynamically change the position of a grid item by changing the name of the grid lines used to position it. * fast/css-grid-layout/grid-item-position-changed-dynamic-expected.txt: Merged from Blink r153913 by <jchaffraix@chromium.org>. * fast/css-grid-layout/grid-item-position-changed-dynamic.html: Ditto. * fast/css-grid-layout/named-grid-lines-with-named-grid-areas-resolution-expected.txt: Added. * fast/css-grid-layout/named-grid-lines-with-named-grid-areas-resolution.html: Added. Canonical link: https://commits.webkit.org/147556@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@164869 268f45cc-cd09-0410-ab3c-d52691b4dbfc
- Loading branch information
Showing
11 changed files
with
694 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
This test checks that we properly recompute our internal grid when a grid item is moved. | ||
|
||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<script> | ||
if (window.testRunner) | ||
testRunner.overridePreference("WebKitCSSGridLayoutEnabled", 1); | ||
</script> | ||
<link href="resources/grid.css" rel="stylesheet"> | ||
<style type="text/css"> | ||
.grid { | ||
-webkit-grid-template-columns: "col" 50px "col" 100px "col" 200px "col"; | ||
-webkit-grid-template-rows: "row" 70px "row" 140px "row" 280px "row"; | ||
} | ||
.differentNamedGridLines { | ||
-webkit-grid-template-columns: "col1" 50px "col2" 100px "col3" 200px "col4"; | ||
-webkit-grid-template-rows: "row1" 70px "row2" 140px "row3" 280px "row4"; | ||
} | ||
</style> | ||
<script src="../../resources/check-layout.js"></script> | ||
<script> | ||
function testPosition(position, size) | ||
{ | ||
gridItem = document.getElementsByClassName("grid")[0].firstChild; | ||
gridItem.style.webkitGridColumn = position.column; | ||
gridItem.style.webkitGridRow = position.row; | ||
gridItem.setAttribute("data-expected-width", size.width); | ||
gridItem.setAttribute("data-expected-height", size.height); | ||
checkLayout(".grid"); | ||
} | ||
|
||
function updateGridItemPosition() | ||
{ | ||
// Test with the same type of positions. | ||
// 1. Explicit grid lines. | ||
testPosition({ 'column': '1 / 2', 'row': '1 / 2' }, { 'width': '50', 'height': '70' }); | ||
testPosition({ 'column': '1 / 3', 'row': '1 / 2' }, { 'width': '150', 'height': '70' }); | ||
|
||
testPosition({ 'column': '1 / 2', 'row': '1 / 3' }, { 'width': '50', 'height': '210' }); | ||
testPosition({ 'column': '1 / 2', 'row': '1 / 2' }, { 'width': '50', 'height': '70' }); | ||
|
||
testPosition({ 'column': '2 / 3', 'row': '1 / 3' }, { 'width': '100', 'height': '210' }); | ||
testPosition({ 'column': '1 / 3', 'row': '1 / 3' }, { 'width': '150', 'height': '210' }); | ||
|
||
testPosition({ 'column': '1 / 3', 'row': '1 / 3' }, { 'width': '150', 'height': '210' }); | ||
testPosition({ 'column': '1 / 3', 'row': '2 / 3' }, { 'width': '150', 'height': '140' }); | ||
|
||
// 2. spans. | ||
testPosition({ 'column': '1 / span 2', 'row': '1 / span 1' }, { 'width': '150', 'height': '70' }); | ||
testPosition({ 'column': '1 / span 1', 'row': '1 / span 1' }, { 'width': '50', 'height': '70' }); | ||
|
||
testPosition({ 'column': '2 / span 1', 'row': '1 / span 1' }, { 'width': '100', 'height': '70' }); | ||
testPosition({ 'column': '2 / span 1', 'row': '1 / span 2' }, { 'width': '100', 'height': '210' }); | ||
|
||
testPosition({ 'column': 'span 2 / 3', 'row': 'span 2 / 3' }, { 'width': '150', 'height': '210' }); | ||
testPosition({ 'column': 'span 1 / 3', 'row': 'span 2 / 3' }, { 'width': '100', 'height': '210' }); | ||
|
||
testPosition({ 'column': 'span 2 / 3', 'row': 'span 1 / 3' }, { 'width': '150', 'height': '140' }); | ||
testPosition({ 'column': 'span 2 / 3', 'row': 'span 2 / 3' }, { 'width': '150', 'height': '210' }); | ||
|
||
// 3. Named grid lines, changing the explicit position. | ||
testPosition({ 'column': '1 / 2 "col"', 'row': '1 / 2 "row"' }, { 'width': '50', 'height': '70' }); | ||
testPosition({ 'column': '1 / 3 "col"', 'row': '1 / 2 "row"' }, { 'width': '150', 'height': '70' }); | ||
|
||
testPosition({ 'column': '1 / 2 "col"', 'row': '1 / 3 "row"' }, { 'width': '50', 'height': '210' }); | ||
testPosition({ 'column': '1 / 2 "col"', 'row': '1 / 2 "row"' }, { 'width': '50', 'height': '70' }); | ||
|
||
testPosition({ 'column': '1 "col" / 4', 'row': '1 "row" / 4' }, { 'width': '350', 'height': '490' }); | ||
testPosition({ 'column': '2 "col" / 4', 'row': '1 "row" / 4' }, { 'width': '300', 'height': '490' }); | ||
|
||
testPosition({ 'column': '2 "col" / 4', 'row': '2 "row" / 4' }, { 'width': '300', 'height': '420' }); | ||
testPosition({ 'column': '2 "col" / 4', 'row': '1 "row" / 4' }, { 'width': '300', 'height': '490' }); | ||
|
||
// 4. Named grid lines, changing the name of the grid lines. | ||
testPosition({ 'column': '1 / 3 "col"', 'row': '1 / 2 "row"' }, { 'width': '150', 'height': '70' }); | ||
testPosition({ 'column': '1 / 3 "invalid"', 'row': '1 / 2 "row"' }, { 'width': '50', 'height': '70' }); | ||
|
||
testPosition({ 'column': '1 / 4 "col"', 'row': '1 / 4 "invalid"' }, { 'width': '350', 'height': '70' }); | ||
testPosition({ 'column': '1 / 4 "col"', 'row': '1 / 4 "row"' }, { 'width': '350', 'height': '490' }); | ||
|
||
testPosition({ 'column': '2 "invalid" / 4', 'row': '1 "row" / 4' }, { 'width': '350', 'height': '490' }); | ||
testPosition({ 'column': '2 "col" / 4', 'row': '1 "row" / 4' }, { 'width': '300', 'height': '490' }); | ||
|
||
testPosition({ 'column': '2 "col" / 4', 'row': '2 "row" / 4' }, { 'width': '300', 'height': '420' }); | ||
testPosition({ 'column': '2 "col" / 4', 'row': '2 "invalid" / 4' }, { 'width': '300', 'height': '490' }); | ||
|
||
// 5. Span named grid lines, changing the grid line number. | ||
testPosition({ 'column': '1 / span 3 "col"', 'row': '1 / span 2 "row"' }, { 'width': '350', 'height': '210' }); | ||
testPosition({ 'column': '1 / span 2 "col"', 'row': '1 / span 2 "row"' }, { 'width': '150', 'height': '210' }); | ||
|
||
testPosition({ 'column': '2 / span 3 "col"', 'row': '1 / span 2 "row"' }, { 'width': '300', 'height': '210' }); | ||
testPosition({ 'column': '2 / span 3 "col"', 'row': '1 / span 1 "row"' }, { 'width': '300', 'height': '70' }); | ||
|
||
testPosition({ 'column': 'span 2 "col" / 3', 'row': 'span 2 "row" / 4' }, { 'width': '150', 'height': '420' }); | ||
testPosition({ 'column': 'span 1 "col" / 3', 'row': 'span 2 "row" / 4' }, { 'width': '100', 'height': '420' }); | ||
|
||
testPosition({ 'column': 'span 2 "col" / 3', 'row': 'span 2 "row" / 4' }, { 'width': '150', 'height': '420' }); | ||
testPosition({ 'column': 'span 2 "col" / 3', 'row': 'span 3 "row" / 4' }, { 'width': '150', 'height': '490' }); | ||
|
||
// Test transition across grid lines types. | ||
// 1. Explicit <-> spans. | ||
testPosition({ 'column': '1 / 3', 'row': '1 / 2' }, { 'width': '150', 'height': '70' }); | ||
testPosition({ 'column': '1 / span 3', 'row': '1 / 2' }, { 'width': '350', 'height': '70' }); | ||
|
||
testPosition({ 'column': '1 / 3', 'row': '1 / span 2' }, { 'width': '150', 'height': '210' }); | ||
testPosition({ 'column': '1 / 3', 'row': '1 / 2' }, { 'width': '150', 'height': '70' }); | ||
|
||
testPosition({ 'column': 'span 1 / 3', 'row': '1 / 2' }, { 'width': '100', 'height': '70' }); | ||
testPosition({ 'column': '1 / 3', 'row': '1 / 2' }, { 'width': '150', 'height': '70' }); | ||
|
||
testPosition({ 'column': '1 / 3', 'row': '1 / 4' }, { 'width': '150', 'height': '490' }); | ||
testPosition({ 'column': '1 / 3', 'row': 'span 2 / 4' }, { 'width': '150', 'height': '420' }); | ||
|
||
// 2. Span <-> named grid lines. | ||
testPosition({ 'column': '1 / "col" 3', 'row': '1 / span 4' }, { 'width': '150', 'height': '490' }); | ||
testPosition({ 'column': '1 / span 3', 'row': '1 / span 4' }, { 'width': '350', 'height': '490' }); | ||
|
||
testPosition({ 'column': '1 / "col" 3', 'row': '1 / span 3' }, { 'width': '150', 'height': '490' }); | ||
testPosition({ 'column': '1 / "col" 3', 'row': '1 / "row" 3' }, { 'width': '150', 'height': '210' }); | ||
|
||
testPosition({ 'column': 'span 1 / 3', 'row': 'span 2 / 4' }, { 'width': '100', 'height': '420' }); | ||
testPosition({ 'column': '1 "col" / 3', 'row': 'span 2 / 4' }, { 'width': '150', 'height': '420' }); | ||
|
||
testPosition({ 'column': 'span 1 / 3', 'row': '"col" 1 / 4' }, { 'width': '100', 'height': '490' }); | ||
testPosition({ 'column': 'span 1 / 3', 'row': 'span 1 / 4' }, { 'width': '100', 'height': '280' }); | ||
|
||
// 3. Named grid lines to span named grid line. | ||
testPosition({ 'column': '1 / "col" 3', 'row': '1 / span 4' }, { 'width': '150', 'height': '490' }); | ||
testPosition({ 'column': '1 / span "col" 3', 'row': '1 / span 4' }, { 'width': '350', 'height': '490' }); | ||
|
||
testPosition({ 'column': '1 / "col" 3', 'row': '1 / span "row" 3' }, { 'width': '150', 'height': '490' }); | ||
testPosition({ 'column': '1 / "col" 3', 'row': '1 / "row" 3' }, { 'width': '150', 'height': '210' }); | ||
|
||
testPosition({ 'column': 'span "col" 1 / 3', 'row': 'span 2 / 4' }, { 'width': '100', 'height': '420' }); | ||
testPosition({ 'column': '1 "col" / 3', 'row': 'span 2 / 4' }, { 'width': '150', 'height': '420' }); | ||
|
||
testPosition({ 'column': 'span "col" 1 / 3', 'row': '"col" 1 / 4' }, { 'width': '100', 'height': '490' }); | ||
testPosition({ 'column': 'span "col" 1 / 3', 'row': 'span "col" 1 / 4' }, { 'width': '100', 'height': '280' }); | ||
|
||
// 4. Explicit <-> named grid lines. | ||
// We need to modify the grid's definitions so that we have explicit and named grid lines not match anymore. | ||
var gridElement = document.getElementsByClassName("grid")[0]; | ||
gridElement.classList.add("differentNamedGridLines"); | ||
|
||
testPosition({ 'column': '1 / "col4" 3', 'row': '1 / 4' }, { 'width': '350', 'height': '490' }); | ||
testPosition({ 'column': '1 / 3', 'row': '1 / 4' }, { 'width': '150', 'height': '490' }); | ||
|
||
testPosition({ 'column': '1 / "col4" 3', 'row': '1 / 4' }, { 'width': '350', 'height': '490' }); | ||
testPosition({ 'column': '1 / "col4" 3', 'row': '1 / "row3" 4' }, { 'width': '350', 'height': '210' }); | ||
|
||
testPosition({ 'column': '"col2" 1 / 4', 'row': '1 "row2" / 4' }, { 'width': '300', 'height': '420' }); | ||
testPosition({ 'column': '1 / 4', 'row': '1 "row2" / 4' }, { 'width': '350', 'height': '420' }); | ||
|
||
testPosition({ 'column': '"col2" 1 / 4', 'row': '1 / 4' }, { 'width': '300', 'height': '490' }); | ||
testPosition({ 'column': '"col2" 1 / 4', 'row': '1 "row2" / 4' }, { 'width': '300', 'height': '420' }); | ||
|
||
// 5. Span <-> span named grid lines. | ||
testPosition({ 'column': '1 / span "col4" 2', 'row': '3 / span 1' }, { 'width': '350', 'height': '280' }); | ||
testPosition({ 'column': '1 / span 2', 'row': '3 / span 1' }, { 'width': '150', 'height': '280' }); | ||
|
||
testPosition({ 'column': '1 / span "col4" 3', 'row': '1 / span 4' }, { 'width': '350', 'height': '490' }); | ||
testPosition({ 'column': '1 / span "col4" 3', 'row': '1 / span "row3" 4' }, { 'width': '350', 'height': '210' }); | ||
|
||
testPosition({ 'column': 'span 2 / 4', 'row': 'span 1 / 4' }, { 'width': '300', 'height': '280' }); | ||
testPosition({ 'column': 'span "col1" 2 / 4', 'row': 'span 1 / 4' }, { 'width': '350', 'height': '280' }); | ||
|
||
testPosition({ 'column': 'span 2 / 4', 'row': 'span 1 / 4' }, { 'width': '300', 'height': '280' }); | ||
testPosition({ 'column': 'span 2 / 4', 'row': 'span "row2" 1 / 4' }, { 'width': '300', 'height': '420' }); | ||
|
||
// 6. Explicit to span named grid line. | ||
testPosition({ 'column': '1 / 2', 'row': '2 / span "row3" 1' }, { 'width': '50', 'height': '140' }); | ||
testPosition({ 'column': '1 / span "col3" 2', 'row': '2 / span "row3" 1' }, { 'width': '150', 'height': '140' }); | ||
|
||
testPosition({ 'column': '1 / 2', 'row': '2 / span "row3" 4' }, { 'width': '50', 'height': '140' }); | ||
testPosition({ 'column': '1 / 2', 'row': '2 / 4' }, { 'width': '50', 'height': '420' }); | ||
|
||
testPosition({ 'column': 'span "col2" 1 / 4', 'row': 'span "row1" 3 / 4' }, { 'width': '300', 'height': '490' }); | ||
testPosition({ 'column': '1 / 4', 'row': 'span "row1" 3 / 4' }, { 'width': '350', 'height': '490' }); | ||
|
||
testPosition({ 'column': 'span "col2" 1 / 4', 'row': 'span "row1" 3 / 4' }, { 'width': '300', 'height': '490' }); | ||
testPosition({ 'column': 'span "col2" 1 / 4', 'row': '3 / 4' }, { 'width': '300', 'height': '280' }); | ||
} | ||
window.addEventListener("load", updateGridItemPosition, false); | ||
</script> | ||
<body> | ||
|
||
<p>This test checks that we properly recompute our internal grid when a grid item is moved.</p> | ||
|
||
<div class="grid"><div class="sizedToGridArea"></div></div> | ||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
This test checks that we resolve named grid line per the specification. | ||
|
||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS | ||
PASS |
Oops, something went wrong.