Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Unified Diff: Source/core/rendering/RenderGrid.cpp

Issue 637033003: [CSS Grid Layout] Fix positioned grid children position and size (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Remove FIXME Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/rendering/RenderGrid.cpp
diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp
index 11474d6b9153b483983e0f05f4bbff8f4b23fdc0..c490ed0452ee217aaf7ae2e58c32300d04bdcf3c 100644
--- a/Source/core/rendering/RenderGrid.cpp
+++ b/Source/core/rendering/RenderGrid.cpp
@@ -224,6 +224,10 @@ void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
return;
}
+ // Positioned items that shouldn't take up space or otherwise participate in the layout of the grid.
+ if (newChild->isOutOfFlowPositioned())
+ return;
+
// If the new child has been inserted inside an existent anonymous block, we can simply ignore it as the anonymous
// block is an already known grid item.
if (newChild->parent() != this)
@@ -252,19 +256,30 @@ void RenderGrid::addChild(RenderObject* newChild, RenderObject* beforeChild)
void RenderGrid::addChildToIndexesMap(RenderBox& child)
{
ASSERT(!m_gridItemsIndexesMap.contains(&child));
- RenderBox* sibling = child.nextSiblingBox();
+ RenderBox* sibling;
+ for (sibling = child.nextSiblingBox(); sibling; sibling = sibling->nextSiblingBox()) {
Julien - ping for review 2014/11/18 21:12:44 nextSiblingBox doesn't check the type and IIRC we
Manuel Rego 2014/11/19 15:18:29 We solved those issues directly in RenderGrid::add
Julien - ping for review 2014/11/19 18:46:43 I didn't have a good way forward, only mentioned t
+ if (!sibling->isOutOfFlowPositioned())
+ break;
+ }
bool lastSibling = !sibling;
- if (lastSibling)
- sibling = child.previousSiblingBox();
+ if (lastSibling) {
+ for (sibling = child.previousSiblingBox(); sibling; sibling = sibling->previousSiblingBox()) {
+ if (!sibling->isOutOfFlowPositioned())
+ break;
+ }
+ }
size_t index = 0;
if (sibling)
index = lastSibling ? m_gridItemsIndexesMap.get(sibling) + 1 : m_gridItemsIndexesMap.get(sibling);
if (sibling && !lastSibling) {
- for (; sibling; sibling = sibling->nextSiblingBox())
+ for (; sibling; sibling = sibling->nextSiblingBox()) {
+ if (sibling->isOutOfFlowPositioned())
+ continue;
m_gridItemsIndexesMap.set(sibling, m_gridItemsIndexesMap.get(sibling) + 1);
+ }
}
m_gridItemsIndexesMap.set(&child, index);
@@ -286,6 +301,9 @@ void RenderGrid::removeChild(RenderObject* child)
return;
}
+ if (child->isOutOfFlowPositioned())
+ return;
+
const RenderBox* childBox = toRenderBox(child);
GridCoordinate coordinate = m_gridItemCoordinate.take(childBox);
@@ -898,6 +916,10 @@ void RenderGrid::placeItemsOnGrid()
Vector<RenderBox*> autoMajorAxisAutoGridItems;
Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
+ if (child->isOutOfFlowPositioned()) {
+ continue;
+ }
+
// FIXME: We never re-resolve positions if the grid is grown during auto-placement which may lead auto / <integer>
// positions to not match the author's intent. The specification is unclear on what should be done in this case.
OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *child, ForRows);
@@ -940,6 +962,10 @@ void RenderGrid::populateExplicitGridAndOrderIterator()
ASSERT(m_gridItemsIndexesMap.isEmpty());
size_t childIndex = 0;
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ if (child->isOutOfFlowPositioned()) {
Julien - ping for review 2014/11/18 21:12:44 FWIW that's the kind of code that makes me advocat
Manuel Rego 2014/11/19 15:18:29 Yeah, I understand what you mean, in several cases
+ continue;
+ }
+
populator.collectChild(child);
m_gridItemsIndexesMap.set(child, childIndex++);
@@ -1098,10 +1124,9 @@ void RenderGrid::layoutGridItems()
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
if (child->isOutOfFlowPositioned()) {
- // FIXME: Absolute positioned grid items should have a special
- // behavior as described in the spec (crbug.com/273898):
- // http://www.w3.org/TR/css-grid-1/#abspos-items
child->containingBlock()->insertPositionedObject(child);
+ adjustPositionedGridItem(child);
+ continue;
}
// Because the grid area cannot be styled, we don't need to adjust
@@ -1145,6 +1170,82 @@ void RenderGrid::layoutGridItems()
setLogicalHeight(logicalHeight() + borderAndPaddingLogicalHeight());
}
+void RenderGrid::adjustPositionedGridItem(RenderBox* child)
+{
+ bool containerHasHorizontalWritingMode = isHorizontalWritingMode();
+ RenderLayer* childLayer = child->layer();
+ childLayer->setStaticInlinePosition(containerHasHorizontalWritingMode ? borderLeft() + paddingLeft() : borderTop() + paddingTop());
+ childLayer->setStaticBlockPosition(containerHasHorizontalWritingMode ? borderTop() + paddingTop() : borderLeft() + paddingLeft());
+}
+
+void RenderGrid::layoutPositionedObjects(bool relayoutChildren, PositionedLayoutBehavior info)
+{
+ TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+ if (!positionedDescendants)
+ return;
+
+ RenderBox* child;
Julien - ping for review 2014/11/18 21:12:44 Why is child defined outside the for-loop?
Manuel Rego 2014/11/19 15:18:29 A mistake, sorry.
+ TrackedRendererListHashSet::iterator end = positionedDescendants->end();
+ for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
+ child = *it;
+
+ if (child->style()->position() == AbsolutePosition) {
Julien - ping for review 2014/11/18 21:12:44 Fixed positioned elements are never handled here.
Manuel Rego 2014/11/19 15:18:29 Yeah, I think you're right. I've removed the if an
+ LayoutUnit columnBreadth = clientLogicalWidth();
+ LayoutUnit columnOffset = offsetForAbsolutelyPositionedChild(*child, ForColumns, columnBreadth);
+ LayoutUnit rowBreadth = clientLogicalHeight();
+ LayoutUnit rowOffset = offsetForAbsolutelyPositionedChild(*child, ForRows, rowBreadth);
+
+ bool containerHasHorizontalWritingMode = isHorizontalWritingMode();
+ RenderLayer* childLayer = child->layer();
+ childLayer->setStaticInlinePosition(childLayer->staticInlinePosition() + (containerHasHorizontalWritingMode ? columnOffset : rowOffset));
+ childLayer->setStaticBlockPosition(childLayer->staticBlockPosition() + (containerHasHorizontalWritingMode ? rowOffset : columnOffset));
+
+ child->setOverrideContainingBlockContentLogicalWidth(columnBreadth);
Julien - ping for review 2014/11/18 21:12:44 columnBreadth is the client box, which is the padd
Manuel Rego 2014/11/19 15:18:29 It's the padding box of the grid container, and it
Julien - ping for review 2014/11/19 18:46:43 You're totally right about the specification. I me
+ child->setOverrideContainingBlockContentLogicalHeight(rowBreadth);
+ }
+ }
+
+ RenderBlock::layoutPositionedObjects(relayoutChildren, info);
+}
+
+LayoutUnit RenderGrid::offsetForAbsolutelyPositionedChild(const RenderBox& child, GridTrackSizingDirection direction, LayoutUnit& breadth)
+{
+ LayoutUnit offset = LayoutUnit(0);
+
+ OwnPtr<GridSpan> positions = GridResolvedPosition::resolveGridPositionsFromStyle(*style(), child, direction);
+ if (!positions)
+ return offset;
+
+ if ((direction == ForColumns && !child.style()->gridColumnStart().isAuto()) || (direction == ForRows && !child.style()->gridRowStart().isAuto())) {
+ breadth -= (direction == ForColumns) ? paddingLeft() : paddingTop();
Julien - ping for review 2014/11/18 21:12:44 Columns / rows follow the logical order so those s
Manuel Rego 2014/11/19 15:18:29 Yes, you're totally right. I've added a new test t
+
+ GridResolvedPosition firstPosition = GridResolvedPosition(0);
+ if (positions->resolvedInitialPosition != firstPosition) {
+ for (GridResolvedPosition position = firstPosition; position < positions->resolvedInitialPosition; ++position) {
+ LayoutUnit trackBreadth = (direction == ForColumns) ? m_columnPositions[position.toInt() + 1] - m_columnPositions[position.toInt()] : m_rowPositions[position.toInt() + 1] - m_rowPositions[position.toInt()];
+ breadth -= trackBreadth;
+ offset += trackBreadth;
+ }
+ }
+ } else if ((direction == ForColumns && !child.style()->gridColumnEnd().isAuto()) || (direction == ForRows && !child.style()->gridRowEnd().isAuto())) {
+ offset -= (direction == ForColumns) ? paddingLeft() : paddingTop();
Julien - ping for review 2014/11/18 21:12:44 Same comment, physical properties vs logical ones.
Manuel Rego 2014/11/19 15:18:29 Done.
+ }
+
+ if ((direction == ForColumns && !child.style()->gridColumnEnd().isAuto()) || (direction == ForRows && !child.style()->gridRowEnd().isAuto())) {
+ breadth -= (direction == ForColumns) ? paddingRight() : paddingBottom();
Julien - ping for review 2014/11/18 21:12:44 Ditto.
Manuel Rego 2014/11/19 15:18:29 Done.
+
+ GridResolvedPosition lastPosition = GridResolvedPosition(direction == ForColumns ? gridColumnCount() : gridRowCount());
+ if (positions->resolvedFinalPosition.next() != lastPosition) {
+ for (GridResolvedPosition position = positions->resolvedFinalPosition.next(); position < lastPosition; ++position) {
+ LayoutUnit trackBreadth = (direction == ForColumns) ? m_columnPositions[position.toInt() + 1] - m_columnPositions[position.toInt()] : m_rowPositions[position.toInt() + 1] - m_rowPositions[position.toInt()];
+ breadth -= trackBreadth;
+ }
+ }
+ }
+
+ return offset;
+}
+
GridCoordinate RenderGrid::cachedGridCoordinate(const RenderBox& gridItem) const
{
ASSERT(m_gridItemCoordinate.contains(&gridItem));

Powered by Google App Engine
This is Rietveld 408576698