Skip to content

Commit 94049f5

Browse files
committed
[css-anchor-position-1] Implement position-area in CSS grids
https://bugs.webkit.org/show_bug.cgi?id=290075 rdar://147452098 Reviewed by Alan Baradlay. Integrates grid-area handling and grid container static posititions with position-area calculations in PositionedLayoutConstraints, and updates callers of containingBlockLogical*ForPositioned to use this full logic. Cosmetic fixes: * Clarify what the LogicalBoxAxis argument to the constructor represents. * Update some comments and add section markers. * Rename computeAnchorGeometry for consistency with other methods. * Organize static position computation under a single primary method. * Reorganize data members of PositionedLayoutConstraints into 3 sections: 1. Data about the box and container. 2. Containing block geometry. 3. Box geometry properties. because the previous split about data mutability no longer is accurate. * LayoutTests/TestExpectations: * LayoutTests/imported/w3c/web-platform-tests/css/css-anchor-position/position-area-in-grid-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-anchor-position/position-area-in-grid.html: * Source/WebCore/rendering/PositionedLayoutConstraints.cpp: (WebCore::PositionedLayoutConstraints::PositionedLayoutConstraints): (WebCore::PositionedLayoutConstraints::captureInsets): (WebCore::PositionedLayoutConstraints::captureGridArea): (WebCore::PositionedLayoutConstraints::captureAnchorGeometry): (WebCore::PositionedLayoutConstraints::computeStaticPosition): (WebCore::PositionedLayoutConstraints::computeInlineStaticDistance): (WebCore::PositionedLayoutConstraints::computeBlockStaticDistance): (WebCore::PositionedLayoutConstraints::computeAnchorGeometry): Deleted. * Source/WebCore/rendering/PositionedLayoutConstraints.h: * Source/WebCore/rendering/RenderBox.cpp: (WebCore::RenderBox::computeReplacedLogicalWidthUsing const): (WebCore::RenderBox::computeReplacedLogicalHeightUsing const): (WebCore::RenderBox::availableLogicalHeightUsing const): (WebCore::RenderBox::containingBlockLogicalWidthForPositioned const): (WebCore::RenderBox::containingBlockLogicalHeightForPositioned const): * Source/WebCore/rendering/RenderBox.h: * Source/WebCore/rendering/RenderGrid.cpp: (WebCore::RenderGrid::layoutPositionedObject): (WebCore::RenderGrid::gridAreaColumnRangeForOutOfFlow const): (WebCore::RenderGrid::gridAreaPositionForInFlowGridItem const): (WebCore::RenderGrid::gridAreaPositionForGridItem const): (WebCore::RenderGrid::logicalOffsetForOutOfFlowGridItem const): Deleted. (WebCore::RenderGrid::gridAreaPositionForOutOfFlowGridItem const): Deleted. * Source/WebCore/rendering/RenderGrid.h: Canonical link: https://commits.webkit.org/293946@main
1 parent f77e0a0 commit 94049f5

File tree

9 files changed

+160
-100
lines changed

9 files changed

+160
-100
lines changed

LayoutTests/TestExpectations

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,20 +1725,14 @@ imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-align-
17251725
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-align-self-vertWM-004.html [ ImageOnlyFailure ]
17261726
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-002.html [ ImageOnlyFailure ]
17271727
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-img-002.html [ ImageOnlyFailure ]
1728-
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-img-last-baseline-001.html [ ImageOnlyFailure ]
17291728
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-img-last-baseline-002.html [ ImageOnlyFailure ]
1730-
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-last-baseline-001.html [ ImageOnlyFailure ]
17311729
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-last-baseline-002.html [ ImageOnlyFailure ]
17321730
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-003.html [ ImageOnlyFailure ]
17331731
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-004.html [ ImageOnlyFailure ]
1734-
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-last-baseline-001.html [ ImageOnlyFailure ]
1735-
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-last-baseline-002.html [ ImageOnlyFailure ]
17361732
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-last-baseline-003.html [ ImageOnlyFailure ]
17371733
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-last-baseline-004.html [ ImageOnlyFailure ]
17381734
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-vertWM-003.html [ ImageOnlyFailure ]
17391735
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-vertWM-004.html [ ImageOnlyFailure ]
1740-
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-vertWM-last-baseline-001.html [ ImageOnlyFailure ]
1741-
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-vertWM-last-baseline-002.html [ ImageOnlyFailure ]
17421736
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-vertWM-last-baseline-003.html [ ImageOnlyFailure ]
17431737
imported/w3c/web-platform-tests/css/css-grid/abspos/grid-abspos-staticpos-justify-self-vertWM-last-baseline-004.html [ ImageOnlyFailure ]
17441738
imported/w3c/web-platform-tests/css/css-grid/abspos/orthogonal-positioned-grid-descendants-010.html [ Pass Failure ]
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
FAIL Offsets for position-area: span-bottom span-left and insets: {"left":"auto","right":"auto","top":"auto","bottom":"auto"} assert_equals: Check expected offsetTop expected 150 but got 100
3-
FAIL Offsets for position-area: span-bottom span-left and insets: {"left":"10px","right":"10px","top":"10px","bottom":"10px"} assert_equals: Check expected offsetTop expected 160 but got 260
2+
PASS Offsets for position-area: span-bottom span-left and insets: {"left":"auto","right":"auto","top":"auto","bottom":"auto"}
3+
PASS Offsets for position-area: span-bottom span-left and insets: {"left":"10px","right":"10px","top":"10px","bottom":"10px"}
44

LayoutTests/imported/w3c/web-platform-tests/css/css-anchor-position/position-area-in-grid.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
position: relative;
5757
width: 400px;
5858
height: 400px;
59+
outline: 1px solid;
5960
}
6061

6162
#anchor {
@@ -65,6 +66,7 @@
6566
width: 150px;
6667
height: 75px;
6768
anchor-name: --anchor;
69+
background: blue;
6870
}
6971

7072
#anchored {
@@ -76,6 +78,7 @@
7678
align-self: stretch;
7779
justify-self: stretch;
7880
position-anchor: --anchor;
81+
border: solid orange;
7982
}
8083
</style>
8184

@@ -99,8 +102,8 @@
99102
}
100103

101104
test_position_area("span-bottom span-left", {left:"auto", right:"auto", top:"auto", bottom:"auto"},
102-
{left:200, top:150, width:50, height:150});
105+
{left:100, top:150, width:150, height:150});
103106

104107
test_position_area("span-bottom span-left", {left:"10px", right:"10px", top:"10px", bottom:"10px"},
105-
{left:210, top:160, width:30, height:130});
108+
{left:110, top:160, width:130, height:130});
106109
</script>

Source/WebCore/rendering/PositionedLayoutConstraints.cpp

Lines changed: 95 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,18 @@ static bool shouldFlipStaticPositionInParent(const RenderBox& outOfFlowBox, cons
5454
return parent->writingMode().isBlockFlipped() && parent->isWritingModeRoot();
5555
}
5656

57-
PositionedLayoutConstraints::PositionedLayoutConstraints(const RenderBox& renderer, const RenderStyle& style, LogicalBoxAxis logicalAxis)
57+
PositionedLayoutConstraints::PositionedLayoutConstraints(const RenderBox& renderer, const RenderStyle& style, LogicalBoxAxis selfAxis)
5858
: m_container(downcast<RenderBoxModelObject>(*renderer.container())) // Using containingBlock() would be wrong for relpositioned inlines.
5959
, m_containingWritingMode(m_container->writingMode())
6060
, m_writingMode(style.writingMode())
61-
, m_physicalAxis(logicalAxis == LogicalBoxAxis::Inline ? m_writingMode.inlineAxis() : m_writingMode.blockAxis())
62-
, m_containingAxis(!isOrthogonal() ? logicalAxis : oppositeAxis(logicalAxis))
63-
, m_alignment(m_containingAxis == LogicalBoxAxis::Inline ? style.justifySelf() : style.alignSelf())
61+
, m_physicalAxis(selfAxis == LogicalBoxAxis::Inline ? m_writingMode.inlineAxis() : m_writingMode.blockAxis())
62+
, m_containingAxis(!isOrthogonal() ? selfAxis : oppositeAxis(selfAxis))
6463
, m_style(style)
64+
, m_alignment(m_containingAxis == LogicalBoxAxis::Inline ? style.justifySelf() : style.alignSelf())
6565
, m_defaultAnchorBox(needsAnchor() ? dynamicDowncast<const RenderBoxModelObject>(renderer.defaultAnchorRenderer()) : nullptr)
6666
{
67-
// Compute the baseline containing block info.
67+
68+
// Compute basic containing block info.
6869
auto containingWidth = renderer.containingBlockLogicalWidthForPositioned(*m_container, false);
6970
if (LogicalBoxAxis::Inline == m_containingAxis)
7071
m_containingRange.set(m_container->borderLogicalLeft(), containingWidth);
@@ -73,22 +74,32 @@ PositionedLayoutConstraints::PositionedLayoutConstraints(const RenderBox& render
7374
m_marginPercentageBasis = containingWidth;
7475
m_originalContainingRange = m_containingRange;
7576

76-
computeAnchorGeometry(renderer);
77+
// Adjust for grid-area.
78+
captureGridArea(renderer);
7779

78-
captureInsets(renderer, logicalAxis);
80+
// Capture the anchor geometry and adjust for position-area.
81+
captureAnchorGeometry(renderer);
7982

80-
if (logicalAxis == LogicalBoxAxis::Inline)
81-
computeInlineStaticDistance(renderer);
82-
else
83-
computeBlockStaticDistance(renderer);
83+
// Cache insets and margins, etc.
84+
captureInsets(renderer, selfAxis);
85+
86+
if (m_useStaticPosition)
87+
computeStaticPosition(renderer, selfAxis);
8488

89+
if (containingCoordsAreFlipped()) {
90+
// Ideally this check is incorporated into captureInsets() but currently it needs to happen after computeStaticPosition() because containingCoordsAreFlipped() depends on m_useStaticPosition.
91+
std::swap(m_marginBefore, m_marginAfter);
92+
std::swap(m_insetBefore, m_insetAfter);
93+
}
94+
95+
// Compute the inset-modified containing block.
8596
m_insetModifiedContainingRange = m_containingRange;
8697
m_insetModifiedContainingRange.shiftMinEdgeBy(insetBeforeValue());
8798
m_insetModifiedContainingRange.shiftMaxEdgeBy(-insetAfterValue());
8899
}
89100

90-
PositionedLayoutConstraints::PositionedLayoutConstraints(const RenderBox& renderer, LogicalBoxAxis logicalAxis)
91-
: PositionedLayoutConstraints(renderer, renderer.style(), logicalAxis)
101+
PositionedLayoutConstraints::PositionedLayoutConstraints(const RenderBox& renderer, LogicalBoxAxis selfAxis)
102+
: PositionedLayoutConstraints(renderer, renderer.style(), selfAxis)
92103
{
93104
}
94105

@@ -128,22 +139,41 @@ void PositionedLayoutConstraints::captureInsets(const RenderBox& renderer, const
128139
m_insetAfter = m_style.logicalBottom();
129140
}
130141

131-
if (containingCoordsAreFlipped()) {
132-
std::swap(m_marginBefore, m_marginAfter);
133-
std::swap(m_insetBefore, m_insetAfter);
134-
}
135-
136142
if (m_defaultAnchorBox) {
137143
// If the box uses anchor-center and does have a default anchor box,
138144
// any auto insets are set to zero.
139145
if (m_insetBefore.isAuto())
140146
m_insetBefore = Length(0, LengthType::Fixed);
141147
if (m_insetAfter.isAuto())
142148
m_insetAfter = Length(0, LengthType::Fixed);
149+
m_useStaticPosition = false;
143150
}
144151
}
145152

146-
void PositionedLayoutConstraints::computeAnchorGeometry(const RenderBox& renderer)
153+
// MARK: - Adjustments to the containing block.
154+
155+
void PositionedLayoutConstraints::captureGridArea(const RenderBox& renderer)
156+
{
157+
const CheckedPtr gridContainer = dynamicDowncast<RenderGrid>(m_container.get());
158+
if (!gridContainer)
159+
return;
160+
161+
if (LogicalBoxAxis::Inline == m_containingAxis) {
162+
m_containingRange = gridContainer->gridAreaColumnRangeForOutOfFlow(renderer);
163+
m_marginPercentageBasis = m_containingRange.size();
164+
} else {
165+
m_containingRange = gridContainer->gridAreaRowRangeForOutOfFlow(renderer);
166+
m_marginPercentageBasis = gridContainer->gridAreaColumnRangeForOutOfFlow(renderer).size();
167+
}
168+
169+
if (!startIsBefore()) {
170+
auto containerSize = BoxAxis::Horizontal == m_physicalAxis
171+
? gridContainer->width() : gridContainer->height();
172+
m_containingRange.moveTo(containerSize - m_containingRange.max());
173+
}
174+
}
175+
176+
void PositionedLayoutConstraints::captureAnchorGeometry(const RenderBox& renderer)
147177
{
148178
if (!m_defaultAnchorBox)
149179
return;
@@ -214,6 +244,8 @@ LayoutRange PositionedLayoutConstraints::adjustForPositionArea(const LayoutRange
214244
};
215245
}
216246

247+
// MARK: - Resolving margins and alignment (after sizing).
248+
217249
void PositionedLayoutConstraints::resolvePosition(RenderBox::LogicalExtentComputedValues& computedValues) const
218250
{
219251
// Static position should have resolved one of our insets by now.
@@ -344,26 +376,55 @@ bool PositionedLayoutConstraints::alignmentAppliesStretch(ItemPosition normalAli
344376
return ItemPosition::Stretch == alignmentPosition;
345377
}
346378

347-
void PositionedLayoutConstraints::computeInlineStaticDistance(const RenderBox& renderer)
379+
// MARK: - Static Position Computation
380+
381+
void PositionedLayoutConstraints::computeStaticPosition(const RenderBox& renderer, LogicalBoxAxis selfAxis)
348382
{
349-
if (!m_useStaticPosition)
350-
return;
383+
ASSERT(m_useStaticPosition);
351384

352-
auto* parent = renderer.parent();
353-
auto parentWritingMode = parent->writingMode();
385+
if (is<RenderGrid>(m_container)) {
386+
// Grid Containers have special behavior, see https://www.w3.org/TR/css-grid/#abspos
387+
if (m_container.get() == renderer.parent()) {
388+
// Fake the static layout right here so it integrates with grid-area properly.
389+
m_useStaticPosition = false; // Avoid the static position code path.
390+
m_insetBefore = Length(0, LengthType::Fixed);
391+
m_insetAfter = Length(0, LengthType::Fixed);
354392

355-
// This method is using enclosingBox() which is wrong for absolutely
356-
// positioned grid items, as they rely on the grid area. So for grid items if
357-
// both "left" and "right" properties are "auto", we can consider that one of
358-
// them (depending on the direction) is simply "0".
359-
if (is<RenderGrid>(parent) && parent == renderer.containingBlock()) {
360-
if (parentWritingMode.isLogicalLeftInlineStart())
361-
m_insetBefore.setValue(LengthType::Fixed, 0);
362-
else
363-
m_insetAfter.setValue(LengthType::Fixed, 0);
364-
return;
393+
if (ItemPosition::Auto == m_alignment.position()) {
394+
if (LogicalBoxAxis::Inline == m_containingAxis) {
395+
auto justifyItems = m_container->style().justifyItems();
396+
if (ItemPosition::Legacy != justifyItems.position())
397+
m_alignment = justifyItems;
398+
} else
399+
m_alignment = m_container->style().alignItems();
400+
}
401+
if (ItemPosition::Auto == m_alignment.position() || ItemPosition::Normal == m_alignment.position())
402+
m_alignment.setPosition(ItemPosition::Start);
403+
if (OverflowAlignment::Default == m_alignment.overflow())
404+
m_alignment.setOverflow(OverflowAlignment::Unsafe);
405+
406+
// Unclear if this is spec-compliant, but it is the current interop behavior.
407+
if (m_marginBefore.isAuto())
408+
m_marginBefore = Length(0, LengthType::Fixed);
409+
if (m_marginAfter.isAuto())
410+
m_marginAfter = Length(0, LengthType::Fixed);
411+
return;
412+
}
413+
// Rewind grid-area adjustments and fall through to the existing static position code.
414+
m_containingRange.moveTo(m_originalContainingRange.min());
365415
}
366416

417+
if (selfAxis == LogicalBoxAxis::Inline)
418+
computeInlineStaticDistance(renderer);
419+
else
420+
computeBlockStaticDistance(renderer);
421+
}
422+
423+
void PositionedLayoutConstraints::computeInlineStaticDistance(const RenderBox& renderer)
424+
{
425+
auto* parent = renderer.parent();
426+
auto parentWritingMode = parent->writingMode();
427+
367428
// For orthogonal flows we don't care whether the parent is LTR or RTL because it does not affect the position in our inline axis.
368429
bool haveOrthogonalWritingModes = parentWritingMode.isOrthogonal(m_writingMode);
369430
if (parentWritingMode.isLogicalLeftInlineStart() || haveOrthogonalWritingModes) {
@@ -407,9 +468,6 @@ void PositionedLayoutConstraints::computeInlineStaticDistance(const RenderBox& r
407468

408469
void PositionedLayoutConstraints::computeBlockStaticDistance(const RenderBox& renderer)
409470
{
410-
if (!m_useStaticPosition)
411-
return;
412-
413471
auto* parent = renderer.parent();
414472
bool haveOrthogonalWritingModes = parent->writingMode().isOrthogonal(m_writingMode);
415473
// The static positions from the child's layer are relative to the container block's coordinate space (which is determined

Source/WebCore/rendering/PositionedLayoutConstraints.h

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@
2828
#include "BoxSides.h"
2929
#include "LayoutRange.h"
3030
#include "RenderBox.h"
31+
#include "StyleSelfAlignmentData.h"
3132

3233
namespace WebCore {
3334

34-
struct PositionedLayoutConstraints {
35+
class PositionedLayoutConstraints {
3536
public:
36-
PositionedLayoutConstraints(const RenderBox&, const RenderStyle&, LogicalBoxAxis);
37-
PositionedLayoutConstraints(const RenderBox&, LogicalBoxAxis);
37+
PositionedLayoutConstraints(const RenderBox&, LogicalBoxAxis selfAxis);
38+
PositionedLayoutConstraints(const RenderBox&, const RenderStyle& selfStyleOverride, LogicalBoxAxis selfAxis);
3839

3940
// Logical top or left wrt containing block.
4041
Length marginBefore() const { return m_marginBefore; }
@@ -75,36 +76,34 @@ struct PositionedLayoutConstraints {
7576

7677
private:
7778
void captureInsets(const RenderBox&, const LogicalBoxAxis selfAxis);
78-
void computeAnchorGeometry(const RenderBox&);
79+
void captureGridArea(const RenderBox&);
80+
void captureAnchorGeometry(const RenderBox&);
7981
LayoutRange adjustForPositionArea(const LayoutRange rangeToAdjust, const LayoutRange anchorArea, const BoxAxis containerAxis);
8082

83+
void computeStaticPosition(const RenderBox&, LogicalBoxAxis selfAxis);
8184
void computeInlineStaticDistance(const RenderBox&);
8285
void computeBlockStaticDistance(const RenderBox&);
8386

84-
private:
85-
// These values are captured by the constructor and may be tweaked by the user.
86-
Length m_marginBefore;
87-
Length m_marginAfter;
88-
Length m_insetBefore;
89-
Length m_insetAfter;
90-
91-
// These values are calculated by the constructor.
92-
LayoutRange m_containingRange;
93-
LayoutRange m_originalContainingRange;
94-
LayoutRange m_insetModifiedContainingRange;
95-
LayoutUnit m_marginPercentageBasis;
9687
CheckedPtr<const RenderBoxModelObject> m_container;
9788
const WritingMode m_containingWritingMode;
9889
const WritingMode m_writingMode;
9990
const BoxAxis m_physicalAxis;
10091
const LogicalBoxAxis m_containingAxis;
101-
const StyleSelfAlignmentData& m_alignment;
10292
const RenderStyle& m_style;
93+
StyleSelfAlignmentData m_alignment;
10394
const CheckedPtr<const RenderBoxModelObject> m_defaultAnchorBox; // Only set if needed.
95+
10496
LayoutRange m_anchorArea; // Only valid if defaultAnchor exists.
97+
LayoutRange m_containingRange;
98+
LayoutRange m_originalContainingRange;
99+
LayoutRange m_insetModifiedContainingRange;
100+
LayoutUnit m_marginPercentageBasis;
105101

106-
// These values are cached by the constructor, and should not be changed afterwards.
107102
LayoutUnit m_bordersPlusPadding;
103+
Length m_marginBefore;
104+
Length m_marginAfter;
105+
Length m_insetBefore;
106+
Length m_insetAfter;
108107
bool m_useStaticPosition { false };
109108
};
110109

0 commit comments

Comments
 (0)