Placed in: Home arrow Programming arrow CSS arrow Webkit Bug: Hover and Sibling Selector viagra australia
viagra online
viagra sale
cialis online
cialis australia
Webkit Bug: Hover and Sibling Selector

Not only Internet Explorer has it flaws when it comes to parsing/using the CSS file. Even though the Webkit engine is the best CSS engine out there (at the moment), I was still able to find a little bug while searching for a solution to a problem last week.

Although the bug is really small and you'll probably never need to use it in real life, I did want to give it a little attention (just in case you do want to solve this problem). I found this one since I wanted to create another Proof of Concept for an article here. Of course, I hope this problem could be solved in the next release of the engine.

Webkit Bug

In simple words, this bug occurs when combining the generic sibling selector (in CSS: ~) in combination with the hover event (in CSS: :hover). Dive into the example/source code to see how it looks like, and think about the effect you think it would produce.

Demo Webkit Bug   Download Webkit Bug

Take note this is a webkit bug only: The example works just fine in Firefox, Opera (and yes - even in Internet Explorer!). It doesn't work in those browsers using webkit: Safari and Chrome. Now let's dive into the problem, and look at possible solutions for this bug.

Basics

Let's first dive into the HTML before we look at the problem. This will allow me to make easier references to the goal we're trying to achieve. As usual, I've kept the HTML as simple as possible, just for the sake of the demo.

HTML

 
<div class="green box"></div>
<div class="red box"></div>
<div class="orange box"></div>
<div class="target">
   <p>This is my target text.</p>
</div>

And some (basic) CSS:

 
.box { width:100px; height:100px; }
.green { background-color:green; }
.red { background-color:red; }
.orange { background-color:orange; }

CSS

Nothing really special going on here as you can see: Just a couple of divisions (boxes with colors) and a target text. Do you know what we're trying to achieve already?

The problem

As you might have thought, I try to change the color (text color) of the last element while hovering the dedicated elements before that. In half-tech half-normal words:

“ When hovering a .box, a sibling with the .target class should change. ”

Sounds like a reasonable thing to do. For those who aren't fully familiar with all the CSS selectors, the ~ can be used as a generic sibling selector.

When you have the following CSS:

 
div ~ p { color : green; }

It will target all the p (paragraphs), as long as they follow a div (division). This is what we need, since we need to target a sibling of the boxes.

CSS

So, what's the CSS I would expect to work? Here we go:

 
.green:hover ~ .target { color:green; }
.red:hover ~ .target { color:red; }
.orange:hover ~ .target { color:orange; }

Looks very logical, doesn't it? When you :hover one of the boxes (with a specified class), the sibling .target would change the colour. Sadly, this doesn't work in Safari and Chrome (webkit browser). In all other browsers, this seem to be working fine.

Solutions

Of course, there are workarounds to make it work in those browsers as well (although I would prefer the CSS only solution that is described above).

The first solution I looked at is using a totally different HTML structure, so we don't need the use of the sibling selector. Here's the new HTML:

 
<div class="green box">
   <div class="red box">
      <div class="orange box">
         <div class="target">
            <p>This is my target text.</p>
         </div> 
      </div> 
   </div> 
</div>

HTML

Of course, we'll also need some changes to the CSS (I've added some comments to explain what it does):

CSS

 
/* Move the 2nd and 3rd box to the right and clear the top margin */
.red, .orange, .target { margin-left:110px; margin-top:0; }
 
/* We manually set the width of the text, since it's in a smaller container */
.target { width:470px; }
 
/* We need to override to prevent the color to go orange (the last container) */
.target:hover { color:#777 !important; }
 
/* Now we can use the :hover event for the boxes to set the target color */
.green:hover .target { color:green; }
.red:hover .target { color:red; }
.orange:hover .target { color:orange; }

Since the .target is now a child of the boxes instead of a sibling, it seems to be working nice in all browsers.

Personally, I don't really like this solution since you'll need to change the structure of your HTML. Also, your CSS uses some dirty tricks (like the .target:hover). That's why I wanted to give it another approach, using jQuery.

For this solution, we don't need to change any of the HTML and the generic CSS classes.

 
$(".box").hover(function() {
   // Set the color by using the class name from the box when hovering
   $(this).siblings(".target").css("color", 
      // Since we know the HTML has two classes ("color" and "box"), we'll need to retrive
      // the data from the first one, and set that as the active color.
      $(this).attr("class").split(" ")[0]
   );
}, function() {
  // Reset the color when the hover is done
   $(this).siblings(".target").css("color", "#777");
});

JavaScript

This solution seems to be working in every browser, including those who are running on webkit!

Final thoughts

It's a bummer this doesn't work as expected in Chrome/Safari, especially since those browsers are the Rolls Royce when it comes to CSS. Still, with some additional knowledge you can work around this problem to make it work everywhere.

Demo Webkit Bug   Download Webkit Bug

Have you ever seen this bug before, and if so, how did you handle it? What did you think of the two solutions? And would you know a better one?


Tags:  webkit bug hover sibling selector css

Interested in this topic? You might enjoy another article I've written called

Did you like this article? Subscribe to my feed or email to keep updated on new articles.

Spread the word and submit to:
Digg!Reddit!Del.icio.us!Facebook!StumbleUpon!
 
< Prev   Next >
Subscribe

Subscribe to Marcofolio