Shipyard
logo
THIS SITE IS NO LONGER MAINTAINED. MOST CONTENT HAS BEEN MIGRATED TO ANCHOR HOSTING WEBSITE.
     
     
Advertising
.au domain names
free transfers, registrations and renewals from $69

Australian web hosting PHP, MySQL, Java
from $198/year

Dedicated servers
Australian, Linux and Windows, $175/month
 

Reducing the Awfulness of Rollover Menus

Written by: James Greogry on 04 February 2004

I am constantly amazed at the collective super-intelligence that is the human race. Why? Because, on the whole, people don't ask me what it is that I like least about the web. I'll let you in on a little secret: THERE ARE A LOT OF THINGS I DON'T LIKE ABOUT THE WEB. But if I had to choose just one -- I couldn't. No hope. Of the thousands of possible options I think the least I could narrow it down to would be something in the order of 15. So, if I had to choose the 15 things I liked the least about the web, I would have to say that "rollover menus" would probably be in there.

"But what's so bad about rollovers?" I hear you say. There's a bunch of things, but ultimately my gripe isn't really with the rollover menus per se, it's more the implementation. Their very existence seems to push aside any and all semblence of foresight that the author of this content may once have had. Let me give you an example. I own a pet store and I want to build a website so I can improve my international sales of Emus. I talk to a web designer and a programmer and being the expert in management that I am, I delegate all the "design" work to the designer, and everything after that to the programmer. All good so far. Now, in one of many meetings with my designer at a cafe on Oxford St sipping cafe-lattes, the designer asks me about "navigation". It goes a little like this:

Designer: So, I was thinking about navigation, Dave.
Me: Navigation? You found your way here ok. Oxford St is pretty central
Designer: Right. Forget I said anything.
...
Designer: Oh yeah, so the site navigation -- how do you want people to find their way around your site?
Me: Gee I hadn't thought about that.
Designer: Hmm. Ok. Well, rollover menus always add a bit of pizazz to any site. I think you should use a rollover menu at the top of your page as the primary navigation tool.
Me: Great! So we're done then.
Designer: Not quite.
Me: What do you mean?
Designer: Well, how will people navigate? how are we going to split up your content?
Me: Hmmm. Yes, I see what you mean. Well look, how about this: we'll have one section for each major animal type -- one for mammals, one for reptiles, one for birds and so-on.
Designer: I like it! But let's go with "furry", "flappy" and "fishy". Don't want to confuse your audience with technical terms like that.
Me: Great! Action that imediately!

So far so good. The next day I realise that actually those were really poor decisions. The site shouldn't just shove animals in my customers faces and expect them to buy stuff. They need to feel like I'm an animal lover trying to help them care for their animals. There should be a "caring for your animal" section and a "So, your animal has super-powers" section. No problem, I'll just call my designer and tell him I changed my mind. That conversation goes like this:

Me: Hi.
Designer: Dave! Good to hear from you baby! Listen I've just done those rollover menus we were talking about yesterday and I've gotta say, this is some of my finest work! The site looks FAAABULOUS!
Me: Hey, that's great! But listen, I was thinking about this menu and I think we need to change the headings -- we're not selling brooms here, people need to feel like they're buying into a community here, not ju...
Designer: But Dave, the work's done. I can't separate these images from the text now.
Me: Ok, well how about we just add some more items to the menu?
Designer: Well, we could do that, but I'd need to redo all the others to make them fit.
Me: Oh. Gee, I'm sorry.
Designer: 12 hours! 12 hours of Photoshopping I'LL NEVER GET BACK, DAVE!
Me: Yeah, ok, look, let's just stick with the original idea. We'll redo it later.

And there it is. You're letting your designer drive your content. But fear not, there is a better way. Let's get stuck right into the details. So, basically you have a background image, and you've got some text you want to stick on top of it. When you rollover these images with your mouse, you want something in the image to chage -- typically the background. So let's start there. Here's a pretty picture I took out at McMahon's Point last night:

I really like the effect you get from the lights reflecting on the water captured on a slow shutter speed, so let's use that for our background. We'll crop a bit out and split it up into boxes. For this example I cropped out this section:

with The GIMP, and then split that up into 4 smaller images with Image Magick's convert command line tool, like so:

convert -crop 125x71+0+0 menu-bg.png menu-bg1.png
convert -crop 125x71+126+0 menu-bg.png menu-bg2.png
convert -crop 125x71+251+0 menu-bg.png menu-bg3.png
convert -crop 125x71+376+0 menu-bg.png menu-bg4.png

So, after all that, here's what we end up with:

Now, if you take nothing else away from this article, remember this: Always get your designers to supply you with these "source" images if they're building rollovers. Otherwise you really are stuck if you want to change one of them.

So now what? Well, it turns out that there is a graphics format defined precisely for solving problems just like this one. It's called SVG. It's an XML format (XML looks a lot like HTML for those of you who haven't worked with it before), which is where it helps us here. Being a text based format, we can chop and change the contents of these menu items as easily as editing a simple, clearly laid out text file. So what goes in these text files? Here's an example:

<svg width="125px" height="71px" viewBox="0 0 125 71">
    <image xlink:href="menu-bg1.png" x="0" y="0" width="125" height="71" />
    <text x="62.5" y="45" style="
        font-size: 35px;
        font-weight: bold;
        fill: #ffffff;
        text-anchor:middle;">Furry</text>
</svg>

And before we move on, here's the output:

Here's a brief explanation of what all that means:

  • The <svg width="125px" height="71px" viewBox="0 0 125 71"> part is the header of the SVG file. It's job is basically to say "hi! the contents of this file should be interpreted as SVG, and when you render it it's width should be 125 pixels wide by 71 pixels tall. All the co-ordinates in the file are relative to an imaginary box which spans the points (0, 0) through to (125, 71)". You can do some cool stuff with these settings, but for this job you always want to make sure that your background images, the SVG size and the viewBox are all the same size.
  • The next line: <image xlink:href="menu-bg1.png" x="0" y="0" width="125" height="71" /> should look pretty familiar to anyone who has worked with HTML before. It's essentially an extension of the good ol' <img ...> syntax. The reasons that the file name isn't in a src attribute are related to the fact that SVG is a "proper" XML standard. Referring to external entities is something you do all over the place in XML, and there are a few ways to do it. The xlink:href is the easiest one to use when you're dealing with images. width and height work exactly the same as they would in HTML. The units for them are relative to the viewBox we mentioned in the previous point, but since we've defined the box to be the same size as the output image, you can just think of them as pixels. The x and y attributes are used here and in the next line. Their meaning is very straightforward: they are just the co-ordinates where this "thing" is meant to be placed. x="0" y="0" is the top left corner.
The final (quite long) line actually draws the text. The x and y co-ordinates work exactly as per the image. The numbers I've chosen put the text pretty much in the middle of the output image. The only part that isn't completely transparent is the style part, so we'll take a look at that:
  • font-size: 35px; does exactly what it says -- sets the size of this block of text to be 35 pixels tall.
  • font-weight: bold; sets the text to be "bold face". It looked a bit weedy without this.
  • fill: #ffffff; sets the colour of the text (as you may have guessed from the #ffffff; part). Why 'fill' and not 'color'? SVG is a bit more sophisticated (and complicated) than the CSS2 spec it's formatting language is based on. In short there are two parts of the text that you can choose a colour for - the text itself, and the outline of the text (and either of these can use a gradient or pattern, but that's beside the point). Replacing the 'fill' with 'stroke' will produce text with black fill with a white outline. Go download yourself an SVG graphics program and try it out.
  • text-anchor:middle; is a technicality really. All it does is tell the SVG renderer to treat the x and y co-ordinates as offsets from the viewBox to the middle (horizontally) of the text. That's why the 62.5 was used (it's half of 125, which is the total width of the image).

The only real gotcha when you're doing this stuff is that the syntax is extremly strict. All those missing quotes and close-tags that you might have got away with in HTML will cause the whole thing to explode and not work. It's not such a big deal, and you'll learn to write better HTML from doing it, but it will trip you up if you aren't expecting it, so be careful. I'd suggest just copying these examples directly and editing them until such time as you're confident with the tools.

The Catch

Nothing is without it's problems unfortunately. SVG is not supported very well by browsers at the moment, so just replacing your JPEG files with SVG files in the rollover menu won't work. At least it won't work today. The good news is that this is well and truly a "solved problem". Programmers write code in languages that computers would never be able to run without some serious help, but somehow we get by. The answer is a program called a "compiler" -- it takes the code that programmers can understand and converts it to 1s and 0s that the computer can understand. The tool I use for converting SVG to JPEG is Image Magick's convert utility (the same one I used for cropping the original image). It couldn't be simpler:

convert menu-item1.svg menu-item1.png

And you'll get a PNG file that exactly matches your SVG input. If you prefer you could also get a GIF or JPEG output, just by changing the output filename (the second parameter there). Now, that's great, you have maintainable menu items, and you get stuff that will work today, but you won't be happy when you've got 100 of these things to take care of. Fortunately enough, that's also a solved problem. There's a tool called 'make' that you can use for automating these conversions. Basically, you make a file called 'Makefile', which contains something like this:

all: $(patsubst %.svg,%.png,$(wildcard *.svg))

%.png: %.svg
    convert $< $@

Then you just type 'make' in that directory and it will go through and convert all your SVG files to PNG files.

Epilogue

Of course, that's only half the story. You'll have to write some awful Javascript code to glue it all together, and you'll need to pry these "source images" and the relevant fonts from your designers' (potentially cold and dead) fingers. Even with these hurdles though, it's a good solution to the same problem I see whenever anyone uses rollover menus.

But I run Windows!

Admittedly I've done all my work here on a Linux machine, where all of these tools are installed out-of-the-box. You can get versions of Image Magick and The GIMP for Windows, you should be able to download them from their respective homepages. If you're only dealing with a small number of images, that will probably be enough. For large projects though, you will really want to use make or a similar tool to manage the conversions for you. Microsoft Visual Studio ships with a similar tool called 'nmake', which can probably be persuaded to do this stuff, but I'm afraid I don't know how. The other option is to download Cygwin which includes a Windows port of make, along with a bunch of other helpful tools.

You can download a copy of all the files I used in making those examples in tar.gz or .zip format.


Related Links:

x