BeeBen's Web Programming PagesBee

Please note that these pages date from 2003 and are near prehistoric in internet terms. It was good stuff when it was written, but old hat now.

These pages not maintained and I no longer deal with queries about them. They remain here for historical interest.

CSS and images

Here's a collection of stuff that I haven't seen widely in use. In what follows I've assumed that your CSS is included using the @import technique as the CSS here could horribly confuse the likes of Netscape 4.

 

Putting images under CSS control

If you are using images as part of your page-layout it is likely that you do not want them to appear if a non-CSS2 browser such as Netscape 4 (or a browser with style-sheets turned off) comes along. A case in point is my my homepage where I use little GIF images to round off the corners of the boxes. I don't want to embed the images in the page's HTML code since they are clearly part of the presentation rather than the content, so I put them under control of CSS along with all the other presentational aspects. A bonus of this method is that it further frees your markup from the use of tables.

Example

Look, no tables!

To make the rounded ends I use the CSS background-image property: create a div with the correct dimensions, and then include the image in the background of the div.

The XHTML markup for this example looks like

<div class="centre">
<div class="line">
  <div class="l"> </div>
  <p>Look, no tables!</p>
  <div class="r"> </div>
</div>
</div>

And the CSS for it looks like this,

.centre { text-align: center; }
.line {
    display: block;
    position: relative;
    background: #330099;
    color: #ffff00;
    text-align: center;
    line-height: 37px;
    height: 37px;
    width: 15em;
    margin: 0 auto 2ex auto;
    padding: 0;
}
.line p {
    display: inline;
    font-family: sans-serif;
    font-weight: bold;
    margin: 0;
    padding: 0;
    line-height: 36px;    /* Hack for Mozilla */
}
.line .l, .line .r {
    width: 19px;
    height: 37px;
    position: absolute;
    top: 0;
}
.line .l { left:  0; background-image: url(/gifs/l-ffffff.gif); }
.line .r { right: 0; background-image: url(/gifs/r-ffffff.gif); }

The definitions of most interest are for the .l and .r selectors where you can see how I define the image size (19px by 37px), and include the corresponding background image for each end. These two images are then placed within the predefined .line object. Of course many of these elements are reuseable, so your final CSS code needn't be enormous.

One minor disadvantage of this method is that it cannot be used to resize images on-the-fly. If your div is smaller than the image it will be clipped; if your div is bigger than the image it will be repeated to fill the space. But you probably don't want to be resizing images on the fly anyway.

 

CSS Image Rollovers

The technique for animating CSS text menus - like the menu on the left - is now pretty well-known. I don't think I've ever seen, however, a pure CSS (non-Javascript) menu with images and rollovers. So, this is how to do it.

I have two pure CSS techniques for animating image links with rollovers. The first just changes the background colour (saving on bandwidth by loading only one image); the second is a genuine rollover with multiple images. Warning: irritatingly some of these techniques do not work with Opera 6, although they are all fine in Opera 7.

Rollover background 1

If we have an image with some transparency we can very easily use the a:hover selector to change the backround colour. In this example the image is embedded in the HTML source which means that it will be shown in non-CSS2 browsers (except text browsers!). The code is more complex than for the following example, but it does work in all the browsers I tried. Note that only one image is downloaded in the creating the effect, which beats typical JavaScript rollovers.

Look!

HTML

<a id="look" href="#"><img src="/gifs/look.gif" alt="Look!" /></a>

CSS

a#look {
    display: block;
    width: 86px;
    height: 38px;
    margin: 0 auto;
    text-decoration: none;
    background-color: #ff00ff;
}
a#look img {
    display: block;
    border: 0;
}
a#look:hover {
    background-color: #0000ff;
}

Rollover background 2

This version is simpler. The image is a CSS background image, so it won't appear in a non-CSS2 browser: instead we supply an alternative text link. This is an example of graceful degradation.

HTML

<a id="smiley" href="#"><span class="alt">Smiley!</span></a>

CSS

a#smiley {
    display: block;
    width: 40px;
    height: 40px;
    background-image: url(/gifs/smiley.gif);
    margin: 0 auto;
    background-color: #ff0000;
}
a#smiley:hover {
    background-color: #00ff00;
}
a .alt { display: none; }

Rollover button 1

Now for rollover images without JavaScript! A few methods are outlined here.

The first one uses background images, and uses the a:hover property to change the image when the pointer is over it, so the images don't show if CSS is turned off and we get the alternative text link. It works well with IE6, Netscape 7, Mozilla and Opera 7, but not with Opera 6.

Push!

HTML

<a id="button1" href="#"><span class="alt">Push!</span></a>

CSS

a#button1 {
    display: block;
    width: 70px;
    height: 37px;
    background-image: url(/gifs/button_0.gif);
    margin: 0 auto;
}
a#button1:hover {
    background-image: url(/gifs/button_1.gif);
}
a .alt { display: none; }

A third button state can be given an image by similarly making use of the :active selector. An exercise for the reader.

Rollover button 1a

This is a variant of Button 1. Again we use a CSS background image, but instead of using the a:hover selector to load a new image for the other state of the button we use CSS to change the position of the existing image. This makes use of the fact that background images are clipped if they are oversize. So our button is a single image containing both button states. Normally the top half of the image is displayed, but when the button is hovered over the image is shifted to show the bottom half. So this is the complete image,

Single image containing two buttons

There are a couple of advantages to doing it this way. First, if the button is accessed it reduces the amount of data downloaded—only one image is downloaded instead of two—so it is faster. Second, there is no delay on first access as we wait for the second image to download: it's already there. No complex image-preloading is needed. On the downside, if the button is never accessed then a little bit of bandwidth has been wasted.

Here's the concept in action,

Push!

The HTML and CSS closely resemble that for Button 1. The main difference is in the :hover selector.

HTML

<a id="button1a" href="#"><span class="alt">Push!</span></a>

CSS

a#button1a {
    display: block;
    width: 70px;
    height: 37px;
    background-image: url(/gifs/button_01.gif);
    background-position: 0 0;
    margin: 0 auto;
}
a#button1a:hover {
    background-position: 0 -37px;
}
a .alt { display: none; }

Rollover button 2

Another way to do CSS rollover images is to fiddle with the z-index property of the images, as below. The z-index controls which display elements are shown "on top".

Unfortunately, this doesn't work with IE6 or Opera 6. Opera 7, Mozilla and Netscape 7 work, but in the case of Mozilla it's painfully slow. In CSS2 browsers where the rollover doesn't work just the top image is displayed, which is OK. In non-CSS2 browsers both the top and hover images are shown side by side, which looks odd.

HTML

<div id="container">
<div id="button2">
<a href="#">
<img class="primary" src="/gifs/button_0.gif" alt="Button" />
<img class="rollover" src="/gifs/button_1.gif" alt="Button" />
</a>
</div>
</div>

CSS

#container { position: relative; height: 37px; margin: 2ex; }
#button2 { position: absolute; }
#button2 a img {
    position: absolute;
    left: 0;
    top: 0;
    width: 70px;
    height: 37px;
    border: 0;
}
#button2 a img.primary { z-index: 1; }
#button2 a img.rollover { z-index: -1; }
#button2 a:hover img.rollover { z-index: 2; }

Update: 8 July 2005. With Mozilla 1.7.8 and Firefox this now works perfectly. And Philip Butler of www.whatthebutlersaw.com has found a workaround for IE.

The Internet Explorer workaround involves a small hack. If the background colour of the image is changed as well as the z-index then IE picks up the change and everything works. Philip changes the colour by one RGB value (eg. #ffffff to #fffffe) which is too small a change to be noticeable.

Skin

Valid XHTML 1.0!
Valid CSS2!

Copyright © 2003 Ben Edgington.