It’s not every day you come across a solid bug in WebKit, which it seems to me leads the pack in quality support of CSS. Alexander Futekov emailed to let me know about this one, which somehow I have never personally come across.
The problem is using adjacent (+) or general (~) sibling selectors combined with pseudo classes. Like this:
h1 ~ p { color: black; }
h1:hover ~ p { color: red; }
Nothing wrong with that, right? Seems pretty straightforward. That just doesn’t work in WebKit, nothing happens. There are lots of weird quirks that can affect it and seemingly fix parts of it. Like this:
/* This affects both paragraphs */
h1 ~ p { font: 18px Helvetica, Arial, Sans-Serif; }
/* This works */
h1:hover + p { color: red; }
/* This only affects first
... and does nothing without previous rule */
h1:hover ~ p { color: blue; }
I didn’t test every single one, but there are apparently issues with all the pseudo selectors (:focus, :hover, :checked, :enabled, etc)
A CSS Only Fix!
Alexander also sent a clever CSS only fix to the issue. Use a do-nothing animation on the body
:
/* Warning: while this works, it may cause high CPU load */
<code class="lang-css prettyprint">body { -webkit-animation: bugfix infinite 1s; }
@-webkit-keyframes bugfix { from { padding: 0; } to { padding: 0; } }
WebKit-only fix to a WebKit-only problem. FAIR WARNING: Readers Adam Ferguson and Simon Goellner both wrote in to tell me this fix was the direct cause of some heavy CPU consumption on sites they were working on.
François Germain also has a test page with a proposed fix on it.
Well Documented
This is certainly not the first report of this. Here are some bug reports:
- bugs.webkit.org/show_bug.cgi?id=12520
- bugs.webkit.org/show_bug.cgi?id=17680
- bugs.webkit.org/show_bug.cgi?id=18026
- bugs.webkit.org/show_bug.cgi?id=18027
- bugs.webkit.org/show_bug.cgi?id=26539
- bugs.webkit.org/show_bug.cgi?id=29029
- bugs.webkit.org/show_bug.cgi?id=32695
- bugs.webkit.org/show_bug.cgi?id=45168
And other publications which mention the issue:
- Showing and hiding content with pure CSS3, in the Taking care of the elderly section
- CSS3 :target based interfaces in the Issues with spiders and reptiles section
- dev.opera.com/forums/topic/600712 – a brief discussion of the bug
- Pure CSS collapsible tree menu in the “Another demo, another bug” section
- Breadcrumbs (& CSS3 general sibling selector) in the “Caveats” section
- CSS3 – Almost a good idea but for Safari and Chrome of all browsers, where the webkit browsers are heavily criticized for the bug
- Webkit Bug: Hover and Sibling Selector, an article about the bug featuring a couple of potential fixes.
- Safari CSS :hover and Adjacent Sibling Selector Bug – yet another blog post about the issue
- Safari bug report: Hover with adjacent selector doesn’t work, the Quirksmode take on the problem.
Hrm, interesting. I’ll have to keep this in mind, as am tending to use more and more diverse selectors.
Thanks!
I came across this same thing a month or so ago. It also affects dynamic pseudo selectors combined with stacked adjacent sibling selectors. For example, the following doesn’t work:
/* Does not work in WebKit */
h1:hover + p + p { color: red; }
I also noticed that using -webkit-transition on an adjacent sibling selector caused Chrome to lock up. But that was back in Chrome 3; even though the selector doesn’t work, that lock-up may be gone. I should check that out.
Thanks for sharing Alexander’s solution!
wow, I’ve tried using things like this to make a play button for an animation in css, nice to see a fix
Its like a nice tutorial to me.. I have never been in that much depth ever…
That bug is there for ages, and it’s really annoying. I didn’t know about the fix, nice one!
But I heavily disagree about “quality support of CSS” in Webkit and I’m really surprised to hear such a thing coming from you. In my opinion, Webkit is good at implementing stuff fast, but does so in extremely buggy ways. Mozilla and Opera usually have far more solid implementations, but they take longer to build them.
Well written blog post, and that i already learned that some groups are more inclined than others (since many of us are different) would share the same idea. I hope you bare this blog functioning well.I have posted a blog related your blog if you need any Web design, development, seo, ppc marketing, software development related work please visit our site http://www.ukwebsitedesigncompany.co.uk
I hate when people do this. How would you feel if we all went and left pointless comments with links back to our sites on your blog?
Thanks for posting the fix for this…
Thanks for adding my article Chris – I was really stunned that this doesn’t work in -webkit . Great to see a solution for this problem, but does anybody know why this workaround actually works? It doesn’t make any sense at all!
I know! thats what i was thinking
Hello,
I’m very pleased there’s a workaround for this – this was exactly what I was looking for and someone has done it! But it’s really unfortunate that it is still not fixed in four years.
Thinking about the workaround: the CSS works like this:
1. the first line references the animation to take place; and then
2. the second line tells the padding not to animate.
“bugfix” is just a reference name
So I’m thinking that the Webkit bug has something to do with the padding of body, but only in specific circumstances.
Not sure if anyone else wants to think this through, but I’m wondering:
a) my scrolling site tutorial (the second referenced site) relies on animating an absolutely-positioned element within an fixed-position element. Both of these are contained inside the body. What is the position (static/relative/absolute) of the body if the position is not declared, and what is its padding?
b) does the position of the grandchild affect the padding of the grandfather?
Still, great to see a solution.
i used to think that ~ only affects on jQuery, not in CSS
does + , > , and < can be used in CSS too?
Even more confusing to me, WebKit seems to treat a:link as both a:link and a:visited.
Good to know that there is a workaround for this!
Any follow up on the battery-life-destruction-derby side of this hack?
Notice that the bug is also present in attribute selector + adjacent selector,
i.e .element[data-state=true]~div
fortunately the proposed solution works perfectly.