Bug 242513 - Animation doesn't play with grid and position absolute (bad grid repaint)
Summary: Animation doesn't play with grid and position absolute (bad grid repaint)
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Animations (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL: https://codepen.io/webcompat/pen/QWmEoJz
Keywords: BrowserCompat, InRadar
Depends on:
Blocks:
 
Reported: 2022-07-08 09:03 PDT by Pierre DE SOYRES
Modified: 2022-09-16 01:50 PDT (History)
11 users (show)

See Also:


Attachments
test case (1.11 KB, text/html)
2022-07-11 15:06 PDT, Karl Dubost
no flags Details
test case 2 (613 bytes, text/html)
2022-09-15 12:16 PDT, Oriol Brufau
no flags Details
test case 3 (686 bytes, text/html)
2022-09-16 01:47 PDT, Oriol Brufau
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Pierre DE SOYRES 2022-07-08 09:03:51 PDT
Animation doesn't play when the following conditions are met:

- container uses display: grid
- container uses position: relative
- element to animate uses position: absolute
- element to animate doesn't start on the first grid column (grid-column-start: 2) 


code snippet for reproducing issue:


```html
<!doctype html>
<html lang="en">
<head>
  <style>
    .main {
      height: 100px;
      background-color: #cccccc;
      display: grid;
      grid-template-columns: auto 1fr auto;
      overflow: hidden;
      position: relative;
    }

    .progress-bar {
      bottom: 0;
      grid-column-start: 2;
      height: 20px;
      position: absolute;
      width: 100%;
    }

    .progress-bar-track {
      background-color: red;
      height: 100%;
    }

    .progress {
      animation: progress 3s linear forwards;
    }

    @keyframes progress {
      0% {
        width: 100%;
      }
      100% {
        width: 0;
      }
    }
  </style>
</head>
<body>
  <div class="main">
    <div class="icon">icon</div>
    <div class="content">content</div>
    <div class="close">X</div>

    <div class="progress-bar">
      <div class="progress-bar-track progress"></div>
    </div>
  </div>
</body>
</html>
```
Comment 1 Karl Dubost 2022-07-11 15:06:45 PDT
Created attachment 460799 [details]
test case

https://codepen.io/webcompat/pen/QWmEoJz
Comment 2 Karl Dubost 2022-07-11 15:09:09 PDT
Tested in 

Safari Technology Preview 16.0
Firefox Nightly 104.0a1
Google Chrome Canary 105.0.5172.0

Both Firefox and Chrome plays the animation.
Comment 3 Radar WebKit Bug Importer 2022-07-11 15:09:22 PDT
<rdar://problem/96845845>
Comment 4 Antoine Quint 2022-09-14 03:47:50 PDT
Resizing the window continuously makes the animation show in some way. My guess is that we correctly animate the data structures but there is some invalidation issue lurking here which makes the animation only show if something else forces a layout or redraw.
Comment 5 Antoine Quint 2022-09-14 04:23:17 PDT
To be clear: the animation is for "width" and runs correctly but the rendering fails to update. If you open Web Inspector and pick the Graphics tab, you'll see the animation running and if you hover over it you'll see the target element overlay shrink.
Comment 6 Simon Fraser (smfr) 2022-09-14 16:23:29 PDT
Web inspector shows that layout is changing, and if I turn off grid it animates, so this is a grid repaint bug.
Comment 7 Oriol Brufau 2022-09-15 12:16:01 PDT
Created attachment 462362 [details]
test case 2

This isn't really related to CSS animations, same problem when changing the width with JS.

The problem seems to be that, if the width shrinks from e.g. 100px to 90px, then these 10px need to be repainted. However, if the 1st column is 1px wide, only 10-1=9 pixels will be repainted, the other pixel stays red.

In the original testcase these non-repainted areas touch each other, so it seems the animation is not playing at all. But in this new testcase it's clearer what's happening.
Comment 8 Oriol Brufau 2022-09-16 01:47:48 PDT
Created attachment 462387 [details]
test case 3

This is the minimal testcase for debugging.
Comment 9 Oriol Brufau 2022-09-16 01:50:44 PDT
Basically, the problem is in RenderGrid::layoutPositionedObject

```cpp
    RenderBlock::layoutPositionedObject(child, relayoutChildren, fixedPositionObjectsOnly);

    setLogicalOffsetForChild(child, ForColumns);
    setLogicalOffsetForChild(child, ForRows);
```

where RenderBlock::layoutPositionedObject ends up reaching RenderBox::frameRect like this:

    RenderBlock::layoutPositionedObject
    RenderElement::layoutIfNeeded
    RenderBlock::layout
    RenderBlockFlow::layoutBlock
    RenderBlockFlow::layoutBlockChildren
    RenderBlockFlow::layoutBlockChild
    RenderBlock::layout
    RenderBlockFlow::layoutBlock
    LayoutRepainter::LayoutRepainter
    RenderBox::outlineBoundsForRepaint
    RenderObject::localToContainerQuad
    RenderBox::mapLocalToContainer
    RenderBox::mapLocalToContainer
    RenderBox::offsetFromContainer
    RenderBox::topLeftLocationOffset
    RenderBox::frameRect

But the m_frameRect hasn't been updated yet by setLogicalOffsetForChild!
And calling setLogicalOffsetForChild first would have its own problems.

I guess RenderGrid::layoutPositionedObject needs to use a different approach, it was also problematic for bug 209460.

Changing the location after RenderBlock::layoutPositionedObject was done in bug 172117.
Not sure in Rego or Sergio remember the details about this.