Bug 141789

Summary: Updating :checked pseudo-class with next-sibling combinator can intermittently fail to re-render background SVG images with transition
Product: WebKit Reporter: krinklemail
Component: CSSAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: dino, graouts, hartman.wiki, koivisto, rniwa, sabouhallawa, simon.fraser, volker, webkit-bug-importer, zalan
Priority: P2 Keywords: InRadar
Version: Safari Technology Preview   
Hardware: All   
OS: All   
Attachments:
Description Flags
Reduction
none
Better reduction none

Description krinklemail 2015-02-18 19:13:26 PST
Reduced test case: http://s.codepen.io/Krinkle/debug/JoLyzx (Source code: http://codepen.io/Krinkle/pen/JoLyzx?editors=110)

The check mark often does not appear when clicking the checkbox.

Reproduced with:
* Safari 7.1.3 (9537.85.12.18), AppleWebKit/600.3.18, OSX 10.9.5
* Safari 8.0 (10600.1.25.1), AppleWebKit/600.1.25, OSX 10.10.1
* WebKit Nightly r180270, AppleWebKit/601.1.19+, OSX 10.9.5

The node's `checked` property is toggling, and the native checkbox's appearance is updated. But surrounding elements that should match via the `:checked` selector are ignored. While trivial in this example (given the native checkbox), this technique is used by UI libraries to replace the appearance of the native checkbox (CSS-only; using opacity and z-index). There, the user would perceive the checkbox as being broken (never reaching the checked state).

We narrowed it down to:
* Selector `input[type="checkbox"]:checked + span`.
* The checkbox in question has no custom styling (user agent default).
* The targeted element is a `<span>` with:
 * transition on background-size
 * background-color
 * one background-image using SVG

The bug is evaded by either: removing the transition, or removing the background-color, or using a PNG instead of SVG, or creating a second background alongside the SVG (e.g. a dummy transparent gradient).

-------

Downstream report:
 https://phabricator.wikimedia.org/T89309#1048894

See also:
 https://bugs.webkit.org/show_bug.cgi?id=17680
Comment 1 krinklemail 2018-05-29 05:15:16 PDT
This is still reproducible in the latest Safari Technology Preview (56) and Safari 11.1.

Updated test case: https://codepen.io/Krinkle/full/XYWjRZ

Expected: Ticking a checkbox makes the tick appear. Unticking a checkbox makes the tick disappear.

Actual: The initial state seems to work, but any input from the user is either ignored or applied without the tick appearing.

This works as expected in Chrome, Firefox and Edge.
Comment 2 krinklemail 2018-05-29 05:18:15 PDT
Triaging as affecting all Hardware/OS (this issue is reproducible on Mobile Safari/iPhone as well).

Tentatively raising important as the impact of this is user confusion and potentially corrupted or unintentional destructive actions, due to the user unable to see whether a checkbox is ticked or unticked.

This may affect any number of UI libraries that customise the style of checkboxes on the web.
Comment 3 Ryosuke Niwa 2018-08-15 19:18:14 PDT
Hm... the URL posted are 404 now. Could you attach a reduced test case if you still have access to it?
Comment 4 Derk-Jan Hartman 2018-08-16 01:47:03 PDT
@Ryosuke Try the link in the 2018 comment, that still works for me.
Comment 5 Ryosuke Niwa 2018-08-16 13:30:30 PDT
Created attachment 347296 [details]
Reduction
Comment 6 Ryosuke Niwa 2018-08-16 13:31:24 PDT
(In reply to Derk-Jan Hartman from comment #4)
> @Ryosuke Try the link in the 2018 comment, that still works for me.

Thanks. I was able to make a reduction based on this.

This is a very convoluted bug. It seems to only reproduce with background SVG images and only when transition is specified. It might be some sort of an animation bug.
Comment 7 Ryosuke Niwa 2018-08-16 13:35:21 PDT
Created attachment 347298 [details]
Better reduction
Comment 8 Radar WebKit Bug Importer 2018-08-16 13:36:25 PDT
<rdar://problem/43394425>
Comment 9 Ryosuke Niwa 2018-08-16 13:37:22 PDT
On STP63, you may need to reload "better reduction" 4-5 times before you can reproduce it once.
Comment 10 Ryosuke Niwa 2018-08-16 13:39:03 PDT
It looks like this is a painting or a layout issue because even when the green box fails to render, the computed style of the span has "200% 200%" as the background size.
Comment 11 Antoine Quint 2018-08-17 07:09:13 PDT
We hit this ASSERT when the test fails:

// FIXME: This doesn't take into account the animation timeline so animations will not
// restart on page load, nor will two animations in different pages have different timelines.
Image* SVGImageCache::imageForRenderer(const RenderObject* renderer) const
{
    auto* image = findImageForRenderer(renderer);
    if (!image)
        return &Image::nullImage();
    ASSERT(!image->size().isEmpty());
    return image;
}

So this does seem related to animations. I think Said should take a look and advise as I'm not sure how the SVGImageCache should relate to animations.