WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
209460
[css-grid] grid padding reduces available space for abspos inside grid items
https://bugs.webkit.org/show_bug.cgi?id=209460
Summary
[css-grid] grid padding reduces available space for abspos inside grid items
Carlos Alberto Lopez Perez
Reported
2020-03-23 19:12:37 PDT
Created
attachment 394343
[details]
test case What steps will reproduce the problem? (1) Create a CSS grid with `position: relative; grid: 100px / 100px; padding-left: 20px` (2) Place a grid item inside it. (3) Place an abspos element inside the grid item. (4) Leave the abspos in its static position, but with `grid-column: 1 / 2` (5) Add two floats inside the abspos, each one with `width: 50px`. Or more generally, any content with total width >80px and <=100px, but which can be broken is parts narrower than <=80px each. What is the expected result? The max-content width of the abspos is 50px+50px = 100px, and the grid area is 100px wide, so the abspos has enough space to grow so that the content fits in a single line. What happens instead? For some reason, the `padding-left: 20px` of the grid only lets the abspos grow to be 80px wide, so the floats will appear in different lines. Firefox does this correctly since
https://bugzilla.mozilla.org/show_bug.cgi?id=1520584
Chromium its affected, tracked at
https://bugs.chromium.org/p/chromium/issues/detail?id=921722
Attachments
test case
(522 bytes, text/html)
2020-03-23 19:12 PDT
,
Carlos Alberto Lopez Perez
no flags
Details
Patch
(8.52 KB, patch)
2021-08-31 08:44 PDT
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(8.55 KB, patch)
2021-09-02 01:53 PDT
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(8.85 KB, patch)
2021-09-13 06:20 PDT
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(10.63 KB, patch)
2021-09-14 03:11 PDT
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(10.96 KB, patch)
2021-11-29 05:57 PST
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(23.88 KB, patch)
2021-12-01 05:55 PST
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(23.89 KB, patch)
2021-12-01 06:41 PST
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(22.69 KB, patch)
2021-12-03 03:10 PST
,
zsun
no flags
Details
Formatted Diff
Diff
Patch
(22.54 KB, text/plain)
2021-12-06 03:55 PST
,
zsun
no flags
Details
Show Obsolete
(9)
View All
Add attachment
proposed patch, testcase, etc.
Carlos Alberto Lopez Perez
Comment 1
2020-03-23 19:14:36 PDT
Other test cases are WPT tests css/css-grid/abspos/descendant-static-position-???.html
zsun
Comment 2
2021-08-31 08:44:33 PDT
Created
attachment 436888
[details]
Patch
zsun
Comment 3
2021-09-02 01:53:08 PDT
Created
attachment 437126
[details]
Patch
Javier Fernandez
Comment 4
2021-09-07 09:00:51 PDT
Comment on
attachment 437126
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=437126&action=review
> Source/WebCore/rendering/RenderGrid.cpp:1002 > + // For an abspos element that is a child of the grid item but containing block is the grid container,
I'm not sure I understand this comment, or the code it tries to explain. It says, "abspos element that is "child of the grid item", but then in the code you are using "!child.IsGridItem()"; I don't understand it. Also, the comment says "the containing block is the grid container", but the combination of both clauses is an element that IS NOT a grid item and the RenderGrid element IS NOT the child's containing block; I'm a bit lost, sorry.
> Source/WebCore/rendering/RenderGrid.cpp:1017 > + setLogicalOffsetForChild(child, ForColumns);
If the abspos is not a grid item, are we calling setLogicalOffsetForChild again ? (didn't we call it in line 1006 already ? )
zsun
Comment 5
2021-09-13 06:20:21 PDT
Created
attachment 438034
[details]
Patch
zsun
Comment 6
2021-09-14 03:11:16 PDT
Created
attachment 438118
[details]
Patch
Oriol Brufau
Comment 7
2021-10-25 05:57:16 PDT
Comment on
attachment 438118
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=438118&action=review
> Source/WebCore/rendering/RenderBox.cpp:4088 > + if (containerBlock.isRenderGrid() && !isGridItem() && style().hasStaticInlinePosition(isHorizontalWritingMode()))
Maybe store this in a variable to be reused below? Like bool isAbsPosGridChild = containerBlock.isRenderGrid() && !isGridItem() && style().hasStaticInlinePosition(isHorizontalWritingMode(); if (isAbsPosGridChild) availableSpace += absoluteValue(this->logicalLeft() - containerBlock.borderLogicalLeft() - containerLogicalWidth); LayoutUnit availableWidth = availableSpace - logicalRightValue; computedValues.m_extent = std::min(std::max(preferredMinWidth, availableWidth), preferredWidth); logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue); if (isAbsPosGridChild) logicalLeftValue -= absoluteValue(this->logicalLeft() - containerBlock.borderLogicalLeft() - containerLogicalWidth); Or maybe LayoutUnit absPosGridChildAdjustment = 0; if (containerBlock.isRenderGrid() && !isGridItem() && style().hasStaticInlinePosition(isHorizontalWritingMode()) { absPosGridChildAdjustment = absoluteValue(this->logicalLeft() - containerBlock.borderLogicalLeft() - containerLogicalWidth); availableSpace += absPosGridChildAdjustment; } LayoutUnit availableWidth = availableSpace - logicalRightValue; computedValues.m_extent = std::min(std::max(preferredMinWidth, availableWidth), preferredWidth); logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue + absPosGridChildAdjustment);
> Source/WebCore/rendering/RenderGrid.cpp:1004 > + if (!child.isGridItem() && hasStaticPositionForChild(child, ForColumns))
Again, seems like the conditions could be reused. bool isAbsPosWithStaticPositionForColumns = !child.isGridItem() && hasStaticPositionForChild(child, ForColumns); if (isAbsPosWithStaticPositionForColumns) setLogicalOffsetForChild(child, ForColumns); bool isAbsPosWithStaticPositionForRows = !child.isGridItem() && hasStaticPositionForChild(child, ForRows); if (isAbsPosWithStaticPositionForRows) setLogicalOffsetForChild(child, ForRows); // ... if (!isAbsPosWithStaticPositionForColumns) setLogicalOffsetForChild(child, ForColumns); if (!isAbsPosWithStaticPositionForRows) setLogicalOffsetForChild(child, ForRows);
Oriol Brufau
Comment 8
2021-10-25 06:07:33 PDT
(In reply to Oriol Brufau from
comment #7
)
> bool isAbsPosGridChild = containerBlock.isRenderGrid() && !isGridItem() > && style().hasStaticInlinePosition(isHorizontalWritingMode();
isAbsPosGridItemChild I guess, or whichever name sounds good.
Oriol Brufau
Comment 9
2021-10-25 17:19:17 PDT
The patch seems bad for dynamic pages. Add this at the end of the attached testcase: <script> absolute.style.marginLeft = "200px"; absolute.offsetLeft; absolute.style.marginLeft = "150px"; </script> Then the content area of the abspos is 100px wide, but due to the margin it should only be the min-content, 50px.
zsun
Comment 10
2021-11-29 05:57:06 PST
Created
attachment 445273
[details]
Patch
Oriol Brufau
Comment 11
2021-11-29 17:53:49 PST
Comment on
attachment 445273
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=445273&action=review
> Source/WebCore/rendering/RenderBox.h:676 > + bool isAbsPosGridChild() const { return !isGridItem() && style().hasStaticInlinePosition(isHorizontalWritingMode()); }
The name doesn't describe well what this does, e.g. it doesn't check that the containing block is a grid container. Though when calling from RenderGrid we don't need to check that... Maybe move the method into RenderGrid, call it on the containing block, passing the child as an argument? Then it will be clear that it's just for grid layout even if you don't check that. Maybe call it RenderGrid::NonDirectChildHasStaticInlinePosition or something. Also, I think the isHorizontalWritingMode() should be called on the containing block. Otherwise, the testcase shows some wrong red when adding #absolute { writing-mode: vertical-lr; left: 50px; } or #grid { writing-mode: vertical-lr; } #absolute { writing-mode: horizontal-tb; top: 50px; } Can you add these variations as new WPTs?
> Source/WebCore/rendering/RenderGrid.cpp:1046 > + gridAreaPositionForOutOfFlowChild(child, ForColumns, m_startOfColumnForChild, m_endOfColumnForChild);
Maybe the value should be cleared after RenderBlock::layoutPositionedObject? It doesn't seem harmful, but it seems strange to remember the value for the last abspos that matches this condition... Also, maybe the value could be a pointer, or a std::optional<LayoutUnit>. At the start of RenderGrid::layoutPositionedObject it would be nullptr or !has_value(), here we would set the value, and then clear it again before leaving the function. Then RenderBox::computePositionedLogicalWidthUsing would only have to check if the value is set, without having to check !isGridItem() and style().hasStaticInlinePosition()
> Source/WebCore/rendering/RenderGrid.cpp:1047 > + gridAreaPositionForOutOfFlowChild(child, ForRows, m_startOfRowForChild, m_endOfRowForChild);
No need for ForRows calculation if it's not used.
> Source/WebCore/rendering/RenderGrid.h:215 > + LayoutUnit m_endOfColumnForChild { 0 };
No need for m_endOfColumnForChild, m_startOfRowForChild and m_endOfRowForChild if they are not used?
zsun
Comment 12
2021-12-01 05:55:39 PST
Created
attachment 445567
[details]
Patch
zsun
Comment 13
2021-12-01 06:41:21 PST
Created
attachment 445570
[details]
Patch
Oriol Brufau
Comment 14
2021-12-02 07:28:26 PST
Comment on
attachment 445570
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=445570&action=review
> Source/WebCore/rendering/RenderBox.cpp:4151 > + if (containerBlock.isRenderGrid() && downcast<RenderGrid>(containerBlock).startOfColumnForNonDirectChildWithStaticInlinePosition())
Just `if (containerBlock.isRenderGrid())` is enough.
> Source/WebCore/rendering/RenderGrid.cpp:1035 > +bool RenderGrid::nonDirectChildHasStaticInlinePosition(const RenderBox& child) const
The function now has a single caller, so you don't need it.
> Source/WebCore/rendering/RenderGrid.cpp:1050 > + LayoutUnit startOfColumnForChild;
Not an expert in memory management. But I worry that if the variable is declared inside the block, it can die when leaving the block, causing a use-after-free when using the pointer. Better declare it outside the conditional.
> Source/WebCore/rendering/RenderGrid.cpp:1064 > + if (m_startOfColumnForNonDirectChildWithStaticInlinePosition)
Is there any benefit in checking the condition instead of just assigning to null?
> Source/WebCore/rendering/RenderGrid.h:85 > + LayoutUnit* startOfColumnForNonDirectChildWithStaticInlinePosition() const { return m_startOfColumnForNonDirectChildWithStaticInlinePosition; }
Maybe the name should make it clear that this is basically a temporary value not always available? Possibly adding "cached" in the name, and then no need to be that comprehensive with the rest of the name. cachedStartOfColumnForChild? cachedStartOfColumnForChildIfNeeded? startOfColumnForComputingPositionedLogicalWidth? Not very good at naming things
Oriol Brufau
Comment 15
2021-12-02 08:37:25 PST
Comment on
attachment 445570
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=445570&action=review
> Source/WebCore/rendering/RenderGrid.cpp:1048 > + if (nonDirectChildHasStaticInlinePosition(child)) {
Nit: assert that m_startOfColumnForNonDirectChildWithStaticInlinePosition is null before the conditional.
Oriol Brufau
Comment 16
2021-12-02 12:12:51 PST
Comment on
attachment 445570
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=445570&action=review
> LayoutTests/imported/w3c/web-platform-tests/css/css-grid/abspos/descendant-static-position-005-expected.html:43 > +<div style="margin-top:20px;">
Instead of adding these divs (which are not closed and the nested structure is more tedious to inspect with devtools), why not .grid { margin-bottom: 20px }
> LayoutTests/imported/w3c/web-platform-tests/css/css-grid/abspos/descendant-static-position-005.html:54 > +<div style="margin-top:20px;">
Ditto.
> LayoutTests/imported/w3c/web-platform-tests/css/css-grid/abspos/descendant-static-position-006-expected.html:22 > + float: top;
This is invalid
> LayoutTests/imported/w3c/web-platform-tests/css/css-grid/abspos/descendant-static-position-006.html:31 > + float: top;
Ditto
zsun
Comment 17
2021-12-03 03:10:21 PST
Created
attachment 445828
[details]
Patch
Oriol Brufau
Comment 18
2021-12-03 15:06:36 PST
Comment on
attachment 445828
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=445828&action=review
> Source/WebCore/rendering/RenderBox.cpp:4166 > + absPosGridChildAdjustment = absoluteValue(*startOfColumn - containerBlock.borderLogicalLeft());
Is the absoluteValue() needed here? If so, why not in the "RULE 3" case below?
> Source/WebCore/rendering/RenderBox.cpp:4167 > + availableSpace += absPosGridChildAdjustment;
Nit: instead of availableSpace += absPosGridChildAdjustment; LayoutUnit availableWidth = availableSpace - logicalRightValue; computedValues.m_extent = std::min(std::max(preferredMinWidth, availableWidth), preferredWidth); logicalLeftValue = availableSpace - absPosGridChildAdjustment - (computedValues.m_extent + logicalRightValue); you could use LayoutUnit availableWidth = availableSpace + absPosGridChildAdjustment - logicalRightValue; computedValues.m_extent = std::min(std::max(preferredMinWidth, availableWidth), preferredWidth); logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue); so you avoid having to subtract absPosGridChildAdjustment at the end.
> Source/WebCore/rendering/RenderBox.cpp:4182 > + availableSpace += absPosGridChildAdjustment;
Nit: for consistency with the above, availableSpace += absPosGridChildAdjustment; LayoutUnit availableWidth = availableSpace - logicalLeftValue; could be LayoutUnit availableWidth = availableSpace + absPosGridChildAdjustment - logicalLeftValue;
zsun
Comment 19
2021-12-06 03:55:30 PST
Created
attachment 446023
[details]
Patch
zsun
Comment 20
2021-12-06 04:03:35 PST
(In reply to Oriol Brufau from
comment #18
)
> Comment on
attachment 445828
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=445828&action=review
> > > Source/WebCore/rendering/RenderBox.cpp:4166 > > + absPosGridChildAdjustment = absoluteValue(*startOfColumn - containerBlock.borderLogicalLeft()); > > Is the absoluteValue() needed here? If so, why not in the "RULE 3" case > below?
> Because the m_columnPositions's data is stored ignoring the direction. *startOfColumn can be a value less than 0 for RTL writing mode. And here we are looking at available width adjustment.
> > Source/WebCore/rendering/RenderBox.cpp:4167 > > + availableSpace += absPosGridChildAdjustment; > > Nit: instead of > > availableSpace += absPosGridChildAdjustment; > LayoutUnit availableWidth = availableSpace - logicalRightValue; > computedValues.m_extent = std::min(std::max(preferredMinWidth, > availableWidth), preferredWidth); > logicalLeftValue = availableSpace - absPosGridChildAdjustment - > (computedValues.m_extent + logicalRightValue); > > you could use > > LayoutUnit availableWidth = availableSpace + absPosGridChildAdjustment - > logicalRightValue; > computedValues.m_extent = std::min(std::max(preferredMinWidth, > availableWidth), preferredWidth); > logicalLeftValue = availableSpace - (computedValues.m_extent + > logicalRightValue); > > so you avoid having to subtract absPosGridChildAdjustment at the end. > > > Source/WebCore/rendering/RenderBox.cpp:4182 > > + availableSpace += absPosGridChildAdjustment; > > Nit: for consistency with the above, > > availableSpace += absPosGridChildAdjustment; > LayoutUnit availableWidth = availableSpace - logicalLeftValue; > > could be > > LayoutUnit availableWidth = availableSpace + absPosGridChildAdjustment - > logicalLeftValue;
Patch updated. Thank very much!
Oriol Brufau
Comment 21
2021-12-06 06:30:15 PST
Comment on
attachment 446023
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=446023&action=review
> Source/WebCore/rendering/RenderBox.cpp:4166 > + absPosGridChildAdjustment = absoluteValue(*startOfColumn - containerBlock.borderLogicalLeft());
absoluteValue() still seems wrong. Add this to the bug testcase: /* Negative RenderGrid::startOfColumnForChild() */ #grid { width: 0px; justify-content: center; } /* Use Rule 1 */ #absolute { writing-mode: vertical-lr; inset-inline-end: 0; } Then you will see red, unlike Firefox and Chromium. Removing absoluteValue() fixes it?
Oriol Brufau
Comment 22
2021-12-06 06:45:26 PST
Comment on
attachment 446023
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=446023&action=review
>> Source/WebCore/rendering/RenderBox.cpp:4166 >> + absPosGridChildAdjustment = absoluteValue(*startOfColumn - containerBlock.borderLogicalLeft()); > > absoluteValue() still seems wrong. Add this to the bug testcase: > > /* Negative RenderGrid::startOfColumnForChild() */ > #grid { > width: 0px; > justify-content: center; > } > /* Use Rule 1 */ > #absolute { > writing-mode: vertical-lr; > inset-inline-end: 0; > } > > Then you will see red, unlike Firefox and Chromium. > Removing absoluteValue() fixes it?
Also, this seems broken in orthogonal cases in general (not just negative values), because startOfColumn and containerBlock.borderLogicalLeft() are based on the writing mode of the grid. <!DOCTYPE html> <html> <meta charset="utf-8" /> <style> #grid { position: relative; display: grid; grid: 100px / 100px; border: 3px solid; padding-left: 20px; width: 0px; } #absolute { inset-inline-end: 0; writing-mode: vertical-lr; line-height: 0; position: absolute; background: red; grid-column: 1 / 2; } #absolute > div { float: left; width: 50px; height: 100px; background: green; } </style> There should be no red: <div id="grid"> <div> <div id="absolute"> <div></div> <div></div> </div> </div> </div> </html>
zsun
Comment 23
2022-05-13 02:52:08 PDT
This is another case of "containing block is not parent" for abpos as
bug 233812
. A generic solution for both grid and flexbox probably is the way forward in long term. I'd prefer to this bug open for anyone who has time and effort to take it.
Radar WebKit Bug Importer
Comment 24
2022-09-10 06:33:21 PDT
<
rdar://problem/99778160
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug