New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 2 users

Issue metadata

Status: Fixed
Owner:
NOT IN USE
Closed: Jun 2014
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 1
Type: Bug-Regression



Sign in to add a comment

Adding elements asynchronously breaks :hover combined with adjacent/sibling CSS selector

Reported by ben.p...@openreign.com, May 22 2014

Issue description

UserAgent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36

Example URL:
http://jsfiddle.net/4qExU/

Steps to reproduce the problem:
1. Go to http://jsfiddle.net/4qExU/
2. Be careful not to hover any other DIV, place the mouse over the first DIV.
3. Move to the second.
4. Move back to the first.

What is the expected behavior?
The CSS should turn the hovered DIV green and the adjacent DIV red.

What went wrong?
The adjacent DIV does not turn red until it has been hovered least once. After it has been hovered, it behaves as expected.

Refresh the page to see the problem again.

Does it occur on multiple sites: Yes

Is it a problem with a plugin? No 

Did this work before? N/A 

Does this work in other browsers? Yes 

Chrome version: 35.0.1916.114  Channel: stable
OS Version: 6.3
Flash Version: Shockwave Flash 13.0 r0

This only happens if the DIVs are added asynchronously. If you remove the setTimout, the CSS is applied correctly. If you use XMLHttpRequest, it exhibits the same behaviorn as setTimeout.

Firefox and IE10 work as expected.

The attached example is the same as the jsfiddle.
 
test.html
1.2 KB View Download
Interestingly, if you interact with the DIV CSS after appending it to the DOM, the issue goes away. For example, in the above example:

        container.appendChild(but);
        but.offsetHeight; <--- add this

Comment 2 by Deleted ...@, May 22 2014

We also ran into this bug today, and made an example before finding this report, so we thought we'd post it anyway. Nothing happens at all until you trigger a change in the DOM (like you said), e.g. select one item in the inspector and make it :active.

Example URL:
http://jsfiddle.net/bva4M/3/

Example video:
https://www.youtube.com/watch?v=bMPrnsQRD1s

-- Remon (remon@hackerone.com) & JP (janpaul@factlink.com)

Comment 3 by tkent@chromium.org, May 27 2014

Labels: -Cr-Content Cr-Blink-CSS

Comment 4 by a...@chromium.org, May 28 2014

Labels: -Pri-2 -Type-Bug Pri-1 Type-Bug-Regression M-37
Owner: a...@chromium.org
Status: Untriaged
Able to repro this on Windows7,latest chrome version:37.0.2017.2  as well.

This is a regression issue working fine on 32.0.1700.107 m.

Will provide the narrow bisect and other OS info soon.

Comment 5 by a...@chromium.org, May 29 2014

Cc: r...@opera.com
Labels: -OS-Windows OS-All
Owner: esprehn@chromium.org
Status: Assigned
Reproducible across all platforms on latest canary(#37.0.2019.0) of Linux & Mac as well.

Regressed in M-34.
CL:http://build.chromium.org/f/chromium/perf/dashboard/ui/changelog.html?url=/trunk/src&range=248707%3A248712

BLINK CL:
http://build.chromium.org/f/chromium/perf/dashboard/ui/changelog_blink.html?url=/trunk&range=166394%3A166385

Suspect r166387.

@esprehn:Could you please take a look.

Comment 6 by r...@opera.com, May 29 2014

Public holiday in Norway today, but I can look at it tomorrow (CET), unless esprehn is eager to do it.

Initial guess is that this is about either (children)affectedByHover or childrenAffectedByDirectAdjacentRules is not being set correctly.

Comment 7 by r...@opera.com, May 30 2014

Cc: le...@chromium.org
The problem is that nodes are attached in the reverse order in Element::recalcChildStyle, and attach() clears the dynamic update bits. When you attach the two sibling divs below, the right sibling will be attached first. While calculating its style it sets the childrenAffectedByHover bit on the left div. However, attaching the left div afterwards will reset that flag before recalculating its style.

<style>
div:hover + div { color: green }
</style>
<div>
    <div></div>
    <div></div>
</div>


Note that the case above also failed before r166387. r166387 just made this bug more visible.

CC'ing leviw since he introduced the reversed attach.

Comment 8 by r...@opera.com, May 30 2014

Resetting these bits on attach/detach is wrong the way they're used today. childrenAffectedByHover actually means descendantsOrSiblingSubtreeElementsAffectedByHover.

Another case that has likely been failing since even before the reversed-attach change:

<!DOCTYPE html>
<style>
    div:hover + div {
        background: green;
    }
</style>
<div>
    <div>DIV 1</div>
    <div>DIV 2</div>
</div>
<script>
    setTimeout(function() {
        document.getElementsByTagName("div")[1].style.display = "inline";
    }, 500);
</script>

Here we only reattach the "DIV 1" div, but clearing those affectedBy bits requires all sibling subtrees to be recalculated to recreate those bits correctly.

It should only be necessary to clear those bits when inserting the Node into the DOM. Not on attach/detach.

Comment 9 by r...@opera.com, May 30 2014

Cc: -r...@opera.com esprehn@chromium.org
Owner: r...@opera.com
Project Member

Comment 11 by bugdroid1@chromium.org, May 31 2014

The following revision refers to this bug:
  http://src.chromium.org/viewvc/blink?view=rev&rev=175199

------------------------------------------------------------------
r175199 | rune@opera.com | 2014-05-31T20:19:56.447503Z

Changed paths:
   A http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dynamic/hover-sibling-reattach.html?r1=175199&r2=175198&pathrev=175199
   A http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dynamic/hover-sibling-reattach-expected.txt?r1=175199&r2=175198&pathrev=175199
   M http://src.chromium.org/viewvc/blink/trunk/Source/core/dom/Element.cpp?r1=175199&r2=175198&pathrev=175199

Reset RestyleFlags when Element is removed.

The RestyleFlags are set based on selectors and DOM structure. Wether the
elements are attached or detached is irrelevant. Furthermore, when these
flags are reset, we must be sure all elements which may contribute to these
flags will have their style recalculated in order to set the flags properly.
That is not necessarily the case for attach/detach since siblings, or
descendants of siblings of the detached element will not have their style
recalculated in general.

Instead, reset RestyleFlags when an element is removed from its parent. If
the element is re-inserted into the DOM, siblings and sibling subtrees will
have the style recalculated to update the flags properly.

R=esprehn@chromium.org
BUG= 376139 

Review URL: https://codereview.chromium.org/304183009
-----------------------------------------------------------------

Comment 12 by r...@opera.com, Jun 1 2014

Status: Fixed

Sign in to add a comment