Simple, Backwards Compatible Rollovers

Posted On: February 11, 2012
web-dev.jpg

 

Whenever I am writing the html and css for a website, I like to take the approach of progressive enhancement. This means that I begin by assuming the site will be viewed with only the essential and then adding features as the browser becomes more capable. One step along that path is adding in javascript support. I am going to outline below exactly how I like to implement rollovers so that they work nicely with or without javascript.

 

I am going to create an icon rollover with a basic fade effect. Lets start by getting everything setup. I like to start by making a sprite. This is one image file that contains both the normal and the rollover state of the icon or button. While you don’t have to use a sprite, it helps reduce load time and will make the effect more responsive the first time it is used.

 

Next, we need to have a way to detect whether or not the browser supports javascript. The simplest way to do this is to start by adding in the class “no-js” into the body tag of your page. Then, using javascript, remove that class and add the class “js”. What happens is that if the browser has javascript disabled, your script won’t run and the “no-js” class will remain. If javascript is enabled, your script will run and the body tag will now have the class “js”. Using jQuery, the script will look like this:

 

{syntaxhighlighter class=”brush: js; ruler: true; first-line: 10; highlight: [2, 4, 6]”} $(document).ready(function() { $(‘body’).removeClass(‘no-js’).addClass(‘js’); }); {/syntaxhighlighter}

 

This works great if you only need to detect javascript support however I highly reccomend checking out modernizr for detection of many other browser capabilities.

 

Now that we can detect javascript support, lets take a look at the html for a typical link. A standard like will of course use the standard <a> tag. When doing a fade effect, a single element is not enough. You will need one element for each state. There are 2 possible ways to do this. The first way is to create another element within the <a> tag. If you are going to take this method, your best bet is to encapsulate the link text in a span element. This way, the tag still serves a purpose rather than having an empty tag that will only be used for the rollover. This is very important because you always want text in your links. Empty tags are bad for SEO. I will be showing you how to hide the link text when we get to the CSS.

 

{syntaxhighlighter class=”brush: css; ruler: true; first-line: 10; highlight: [2, 4, 6]”} Link Text {/syntaxhighlighter}

 

This method works great if no other options are available and how I used to do most of my rollovers. I eventually noticed however that 95% of the time I wanted to create a rollover effect, the a tag appeared within another element such as an <li> tag. Using this method, you would use the <li> tag as your base, and the <a> tag as the rollover.

 

{syntaxhighlighter class=”brush: css; ruler: true; first-line: 10; highlight: [2, 4, 6]”}

{/syntaxhighlighter}

You would of course want more than one item in a list but I am going to keep things simple for the example.

 

We can now get to the css. Since this is progressive enhancement, we are going to begin by assuming there will be no javascript support. I will first show you the css and then explain what is happening. For simplicity, I will assume we are using the second html format.

 

{syntaxhighlighter class=”brush: css; ruler: true; first-line: 10; highlight: [2, 4, 6]”} li.button, li.button a { display: block; width: 20px; height: 20px; background: url(sprite.png) 0px 0px no-repeat; text-indent: -9999px; line-height: 0; } .no-js li.button a:hover { background-position: 0px -20px; } js li.button a { background-position: 0px -20px; opacity: 0; filter: alpha(opacity=0);/* IE */ } {/syntaxhighlighter}

 

So here’s what’s happening. We start by setting some basic styles for the <li> and <a> elements. When javascript is not available two things are happening. First, the background image on the <li> element wont matter. This is simply there for the case when javascript does become available. Also, since the background on the <a> will cover it and since it’s a sprite, we aren’t loading any extra images. When someone hovers over the a element, the background of the a element shifts to show the rollover state. The text-indent and line-height settings hide the text that was in the link while maintaining the accessibility and seo advantages. When we know that javascript is available, we are going to utilize both elements to create the rollover fade effect. We start by shifting the background image in the a element so that the rollover state is visible. Since we don’t want that to be visible for the button’s normal state, we then set the opacity to 0 and now the normal state will appear beneath. This makes our final piece of the puzzle incredibly basic.

 

The javascript! Since this won’t even run if javascript is disabled, we don’t have to worry about selecting the .js class. jQuery make this script very simple.

 

{syntaxhighlighter class=”brush: js; ruler: true; first-line: 10; highlight: [2, 4, 6]”} $(document).ready(function() { $(‘li.button a’).mouseenter(function() { $(this).stop().animate({ opacity : 1 }); }).mouseleave(function() { $(this).stop().animate({ opacity : 0 }); }); }); {/syntaxhighlighter}

 

And that’s all there is to it. The above script increases the opacity of the a tag to 100% on rollover and reduces it back to 0 when the mouse leaves. I added in the stop() function to prevent the effect from repeating if the user mouses over the link multiple times in quick succession.