| Summary: | Animation doesn't play with grid and position absolute (bad grid repaint) | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | WebKit | Reporter: | Pierre DE SOYRES <pierre.de-soyres> | ||||||||
| Component: | Animations | Assignee: | Nobody <webkit-unassigned> | ||||||||
| Status: | NEW --- | ||||||||||
| Severity: | Normal | CC: | dino, graouts, graouts, karlcow, mattwoodrow, obrufau, rego, simon.fraser, svillar, webkit-bug-importer, zalan | ||||||||
| Priority: | P2 | Keywords: | BrowserCompat, InRadar | ||||||||
| Version: | WebKit Nightly Build | ||||||||||
| Hardware: | Unspecified | ||||||||||
| OS: | Unspecified | ||||||||||
| URL: | https://codepen.io/webcompat/pen/QWmEoJz | ||||||||||
| Attachments: |
|
||||||||||
Created attachment 460799 [details] test case https://codepen.io/webcompat/pen/QWmEoJz 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. 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. 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. Web inspector shows that layout is changing, and if I turn off grid it animates, so this is a grid repaint bug. 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.
Created attachment 462387 [details]
test case 3
This is the minimal testcase for debugging.
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.
|
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> ```