|
|
|
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: |