Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 221d56a321d694a2a1bbd40e01b929b57735677d
      
https://github.com/WebKit/WebKit/commit/221d56a321d694a2a1bbd40e01b929b57735677d
  Author: Sammy Gill <[email protected]>
  Date:   2025-07-15 (Tue, 15 Jul 2025)

  Changed paths:
    M LayoutTests/TestExpectations
    M Source/WebCore/rendering/PositionedLayoutConstraints.cpp
    M Source/WebCore/rendering/PositionedLayoutConstraints.h

  Log Message:
  -----------
  [Absolute Positioning] Incorrect static position when containing block is a 
grid.
https://bugs.webkit.org/show_bug.cgi?id=295818
rdar://155650719

Reviewed by Alan Baradlay.

compute{Inline,Block}StaticDistance are two helper functions that are
used to compute the static position of a box when we need it for one
of its inset values. The way that this works at a high level is by
taking the static position that lives on the associated RenderLayer,
which is in the coordinate space of the parent, and mapping it to the
box's containing block. One important detail regarding this coordinate
space transformation is that the resulting static position is the box's
position within the containing block's *padding* box since we subtract
out its border. In general, this works for most pieces of content;
however, this could result in an incorrect static position for a box when
its containing block is a grid.

To make the underlying problem a bit easier to understand, I think it's
important to look at an example that has a containing block which is
not a grid and one with a grid containing block. To keep this as simple
as possible, we will only be worrying about the static position in the
inline axis by setting top to 0.

Block container as containing block:

.block {
  position: relative;
  width: 40px;
  height: 40px;
  border-left: 50px solid black;
  padding-left: 30px;
}

.grid > div {
  background: red;
}
.absolute {
  position: absolute;
  background: red;
  grid-column: 1 / 2;
  top: 0;
}
.content {
  float: left;
  width: 20px;
  height: 40px;
  background: green;
}

<div class="block">
  <div>
    <div class="absolute">
      <div class="content"></div>
      <div class="content"></div>
    </div>
  </div>
</div>

 _______________________________________________
|                                               | <- 120px border box width
 -----------------------------------------------
| border          |          |                  |
| 50px            |          |                  |
|                 |          |                  |
|                 | padding  |                  |
|                 | 30px     |                  |
|                 |          |                  |
|                 |          | content          |
|                 |          | 40px             |
|                 |          |                  |
|                 |          |                  |
|                 |          |                  |
|                 |          |                  |
 -----------------------------------------------
                  |                             | <- original containing block 
for abspos
                   -----------------------------

In this example, the original containing block for the absolutely
positioned box is the block container's padding box. When we convert the
static position to the coordinate space, we end up with a value of 30px.
This comes from the fact that the position is located at 120px in the
block container's border box, but we compute it as the location in the
padding box, so 120px - 50px. This value then gets set to the left inset
value for the box, which is okay since the location in the padding box is
exactly the same as the offset from that edge to its static position.

Example with grid as containing block (most styling is the same, only .grid
is different):

.grid {
  position: relative;
  display: grid;
  grid: 40px / 40px;
  border-left: 50px solid black;
  padding-left: 30px;
  width: 20px;
}

.grid > div {
  background: red;
}
.absolute {
  position: absolute;
  background: red;
  grid-column: 1 / 2;
  top: 0;
}
.content {
  float: left;
  width: 20px;
  height: 40px;
  background: green;
}

<div class="grid">
  <div>
    <div class="absolute">
      <div class="content"></div>
      <div class="content"></div>
    </div>
  </div>
</div>

 _______________________________________________
|                                               | <- 120px border box width
 -----------------------------------------------
| border          |          |                  |
| 50px            |          |                  |
|                 |          |                  |
|                 | padding  |                  |
|                 | 30px     |                  |
|                 |          |                  |
|                 |          | grid area
|                 |          | 40px             |
|                 |          |                  |
|                 |          |                  |
|                 |          |                  |
|                 |          |                  |
 -----------------------------------------------
                             |                  | <- original containing block 
for abspos
                              ------------------

In order to not overcomplicate this with extra grid details, the grid
area was computed to be the same size as the block container from the
previous example, and the absolute positioned box's grid properties
specify exactly this area.

This example is almost exactly the same as the previous; however, it is
important to note the difference in the containing block. In this case,
since the containing block is the grid, then its containing block is
set to the grid area determined by its grid area properties.

https://drafts.csswg.org/css-grid-2/#abspos-items

When we convert the static position this time, we end up getting the same
exact value before, which should not be super surprising since the
static position set by the RenderLayer is also the same value. However,
this value no longer makes sense from the perspective of it being the
offset from the containing block. This can end up in an incorrectly
sized and located inset modified containing block. In this case, the location
in the padding box cannot be used as the offset from the containing block since
the containing block starts in the grid area (which in this case is just
the same as the content box, but that is certainly not always the case).

In order to rectify this, we must slightly change how we compute the value
used for the inset. Instead of just computing and directly using the
location in the padding box, we should:

1.) Compute the box's location in the containing block's border box.
2.) Take that value and subtract it from the location of the containing
block, which should be in the same coordinate space.

In the cases where the inset/static position is computed to be the
offset from the padding box, this works out since the containing block's
location is set to the padding box origin.

Unfortunately, this is not the only area that prevents us from computing
the correct value where the containing block is a grid. Before we
actually begin computing the static position code, we have logic that
performs some form of adjustment before we enter the helper functions
(see PositionedLayoutConstraints::computeStaticPosition). It is not
super clear what this is attempting to do, but it completely throws off
the location of the containing block and results in an incorrect static
position. In theory, we should just be able to get rid of this special
logic and apply the new static position computation, but that resulted in
some regressions. So instead, we will just restrict and apply this logic
for certain types of content and grow it over time. Eventually, with
some debugging, we should be able to get to a point where we can remove
it. For now, it is only applied when we are computing the inline offsets,
the direction is LTR, and the parent does not have an orthogonal writing
mode to the containing block.

Canonical link: https://commits.webkit.org/297403@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to