Submit your widget

multiple Text Hover Effect With jQuery

Created 13 years ago   Views 13936   downloads 1925    Author marcofolio
multiple Text Hover Effect With jQuery
View DemoDownload
114
Share |

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.

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.

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.

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

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>

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

/* 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");
});

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