Grow your CSS skills. Land your dream job.

WebKit Adjacent/General Sibling & Pseudo Class Bug

Published by Chris Coyier

Good news everyone! This is fixed in both stable releases of the WebKit browser Safari (5.1) and Chrome (13)

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:

body { -webkit-animation: bugfix infinite 1s; }
@-webkit-keyframes bugfix { from { padding: 0; } to { padding: 0; } }

WebKit-only fix to a WebKit-only problem. Although be forewarned, Adam Ferguson wrote in to tell me this fix was the direct cause of some heavy CPU consumption on a site he was 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:

And other publications which mention the issue:

Comments

  1. Hrm, interesting. I’ll have to keep this in mind, as am tending to use more and more diverse selectors.

    Thanks!

  2. 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; }

  3. 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!

  4. Permalink to comment#

    wow, I’ve tried using things like this to make a play button for an animation in css, nice to see a fix

  5. Its like a nice tutorial to me.. I have never been in that much depth ever…

  6. Permalink to comment#

    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.

  7. 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

    • Permalink to comment#

      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?

  8. Permalink to comment#

    Thanks for posting the fix for this…

  9. Permalink to comment#

    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

    • Corey Mwamba
      Permalink to comment#

      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.

  10. Permalink to comment#

    i used to think that ~ only affects on jQuery, not in CSS

    does + , > , and < can be used in CSS too?

  11. Even more confusing to me, WebKit seems to treat a:link as both a:link and a:visited.

  12. Permalink to comment#

    Good to know that there is a workaround for this!

  13. age401
    Permalink to comment#

    Any follow up on the battery-life-destruction-derby side of this hack?

  14. Mickael
    Permalink to comment#

    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.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".