CSS Tip: Hover effects done properly

(This post is also available in Spanish, translated by Maria Ramos from Webhostinghub.com)

I was checking out Readify’s cool new TFS Now! offering this evening. Under the hood, they’ve solved quite a number of technical challenges which you can hear about during DEV316 at Tech.Ed next week.

This post was triggered by something that jumped out at me when looking at their consumer facing site though… In reality, you’ll find what I talk about here on almost every website that uses hover effects. I’ve chosen to use the TFS Now! site as a the example here because it’s a fairly simple real world page that clearly demonstrates the issue.

On their homepage, you’ll notice these nice big bananas:

image

When you hover over one of them, you get some feedback:

image

All good so far. The CSS used to achieve this is rather simple:

div#pageContainer div.homepage-sections div.benefits a {
    background:transparent url(../yellow-button.png) no-repeat scroll 0%;
}

div#pageContainer div.homepage-sections div.benefits a:hover {
    background:transparent url(../yellow-button-hover.png) no-repeat scroll 0%;
}

Firing up a copy of Fiddler shows pretty clearly that IE loads both the normal image, and hover image as part of the page load:

image 

When you mouse-over the button, IE has the hover image cached so you get the rollover effect instantly.

This is where the problem starts…

When you mouse-off, IE re-loads the normal image. Even though the image is in the client side cache, IE still decides that it needs to call the server to check for any updates. During this time, you get a noticeable flash where there is no image displayed at all. You can see the calls in Fiddler, and the Flash is noticeable even on most localhost tests.

image 

The Solution

It took me a few years of web development to come across a solution for this that didn’t involve the messy pre-loaders and ugly JavaScript hover scripts prominent throughout the 90s. In the end, the solution was remarkably simple and provided a number of other benefits. They’re called sprites.

First up, combine the two image assets into one. For this example, the buttons were 215x98px so I placed them on a 215x196px canvas in Photoshop:

image 

Even if you have unused pixels in one of the grid spaces, keep them both the same size.

This can now be applied using even less CSS then we had before:

div#pageContainer div.homepage-sections div.benefits a {
    background: transparent url(../yellow-button.png) no-repeat left top;
}

div#pageContainer div.homepage-sections div.benefits a:hover {
    background-position: left -98px;
}

You’ll notice that in the hover rule, instead of changing the image I’m now just sliding the image further up within the element.

Loading both styles in the one resource solves the flashing issue, as the image is never actually changing – it’s just moving. We also get some instant IO savings as a result:

image

While 1.7KB might not seem like much, you need to remember that in this scenario that equates to an almost 30% saving. And that doesn’t even include the 798 bytes of HTTP headers we saved too.

Extending this idea and including all six states (two states each for three buttons) as a 3×2 grid gives us even better savings.

The next thing to remember is that you can only have two simultaneous HTTP connections to the same server. Considering the homepage of TFS Now! currently triggers a total of 25 requests, there’s a lot of blocking going on there. Just by optimizing these buttons, we could reduce that by 20%.

The Benefits

All up, with this simple change we:

  • Removed the blank flash on mouse-out
  • Reduced data transfer by ~30%
  • Reduced server requests by 20%, and thus noticeably improved page load time
  • Removed almost duplicate code from the CSS

At this point, I’d say it isn’t worth changing, however it’s a useful technique to keep in mind next time you’re building out a site.

Particularly in cases where you have lots of similar-sized images, such as toolbar icons for a web-interface, you can get significant benefits to both real and perceived performance by loading them as a single image rather than as a series of blocking requests.

Update: Following up from Mitch’s concern that different browsers may have issues moving the image, I can confidently reply that this technique has worked everywhere I’ve ever tried to use it. At Squeeze Creative, everything is tested in IE6 PC, IE7 PC, FF1.5 PC, FF2.0 PC, S3.0 PC, O9 PC, S1.3 Mac, S2.0 Mac, S3.0 Mac, FF1.5 Mac, FF2.0 Mac, and O9 Mac. All up, that’s a pretty exhaustive set of tests. Historically we have tested even more platforms (like FF1.0) and this technique stood up pefectly then too. I focussed on IE7 throughout the post as it shows the clearest ‘flash’, however the problem and the solution are relevant to all browsers.

— 

Was this post useful for you? Let me know!

Which time zone should I set for my server?

This was the question I was faced with last week. I was configuring a VPC image in Sydney, that I was later going to load on to a physical box in San Diego, then use it from anywhere in the world. So which time zone to use?

I decided upon UTC, and now, the more that I think about it, I don’t know why all servers aren’t configured that way.

Advantages to using UTC:

  • No weird shifts/jumps around daylight savings
  • Accidental usage of DateTime.Now in server-side code returns that same value as DateTime.UtcNow anyway
  • Migrating applications and their data, or entire VMs across physical locations becomes easy

Disadvantages to using UTC:

  • Everything is stored in UTC, and thus hard for most humans to deal with mentally. The solution: tools like the Windows Event Viewer and SQL Management Studio should allow you to apply a time zone offset to visible results.

My recommendation: Run all your servers in UTC (that’s “GMT – Greenwich Mean Time” with “Automatically adjust clock for DST” turned OFF).

Maybe Adam can add this to his standards? 😉

Strange server behavior – huge I/O other count for csrss.exe (SOLVED!)

I can’t say this feels right to me:

image

Notice the 603 terabyte value in the “I/O Other Bytes” column for csrss.exe. Oh yeah, and the box has only been up for 24 hours. The number seems to climb by 50 or 60 GB a second when I’m connected via RDC. If I logoff then back on, the count starts again.

I’ve tried Googling it, but found no solutions.

Anybody got any ideas? It doesn’t actually seem to be causing a problem, it’s just out of the ordinary.

The box is a 1.8GHz Core2 Duo running Windows Server 2003 R2 Standard x64 Edition.

Update – I (think) I found the solution!

Following some suggestions in this post’s comments and on Google that this might be a virus, Edward suggested I fire up a copy of SysInternals Process Explorer on the server. I’ve used the SysInternals tools in the past, but not being a server guy by trade meant that I’d forgotten about them.

After finding the process, I was quickly comforted that this wasn’t a virus. The signature was verified, it was executing from the correct path (system32) and it was running under NT AUTHORITY\SYSTEM where I expected it to.

image

If we recall the original symptoms, the count was reset if I logged off RDC and back on again. This didn’t really prove much other than the fact that the process restarted at login. Swapping to the “Performance Graph” tab is Process Explorer did however show some interesting results.

image 

Whenever I minimized my RDC window, it stopped requesting data and the I/O bytes graph was stagnant. As soon as I brought the RDC window back up and started interacting with it, the values skyrocketed. My screenshot doesn’t show it, but that graph was peaking to 80GB!

The end result would seem to be: “that’s just how much stuff is going on to support RDP”.

To me that’s an incredible amount on information being shuffled around and process, but I guess this is why the actual data on the wire is so efficient. Unless anything else comes up, I’m happy to file this in the “amazing but normal” pile.