Alpha Blending on Link Hover

If you like, skip the process and see the final stylesheet.

A friend of mine was designing a site and using images to do rollovers for his navigation. I wanted to suggest to him that he go with plain text links to make the page easier to maintain. The tricky bit though is the rolled over images were alpha blended masks of the background (like Meyer's complexspiral). Meyer uses an alternate image and CSS positioning to make his demo work. I was hoping that opacity support in browsers was to the point that it wouldn't be necessary to do that (since that means any time you want to change your images of color scheme you have to muck about in photoshop).

Borders

A basic trick that is shared by all these is borders that appear on hover. The problem with borders is that they change the width of an element, so the text will change positions. In standards-compliant browsers you can get around this by specifying border-color: transparent for the borders when you don't want to show them. This doesn't work in IE though and so a different type of finagling is needed. I'll mention this once though it is present on all the examples.

What is done is, in order to adjust to the extra width of the border, the element actually gets smaller. The CSS looks like this:

a {
  display: block;
  padding: 10px 30px 10px 15px;
}
a:hover {
  border: solid black;
  border-width: 1px 0px 1px 4px;
  padding: 9px 30px 9px 11px; /* a.padding - a.border */
}

Straight CSS

The CSS3 spec is going to allow for alpha values on colors. Once it is implemented, it will be possible to do this:

a { background-color: rgba(255, 0, 0, .5) }

Unfortunately those days are a ways off and for now it is necessary to use semi-transparent PNGs. PNGs not only support transparency, like GIFs, but also alpha values. I went into the gimp and made a little 1x1 maroon image and made it 75% opaque. Making this the background for link hovers just took this CSS:

a:hover { background-image: url('75_red_alpha.png') }

PNG Support in IE

The problem with this approach is that IE doesn't support alpha values on PNGs. The alpha value is just ignored and the image is displayed as opaque. There is a way around this using a bit of non-standard CSS however:

<!--[if lt IE 7]>
<style type="text/css">
  a { zoom: 1; }
  a:hover {
    background-image: none;
    filter: progid:DXImageTransform.Microsoft.AlphaImageLoader
     (sizingMethod=scale, src='75_red_alpha.png');
  }
</style>
<![endif]-->

There are three IE specific bits here:

Block Anchors in IE

The remaining problem with this in IE has nothing to do with the background. It has to do with the link. These are navigation links to go in the sidebar. Their display is set to block. Unfortunately, in IE the :hover style is only consistently triggered for these elements when the mouse is over the text of the link.

This is a function of the PNG. Note that the first link to the left is hoverable in the entire block (containing Striaght CSS). (It just lacks alpha blending.) The second link flashes except when the cursor is directly over the text of the link, AlphaImageLoader. This is because the loaded PNG apparently makes IE think the element is not hovered, so it takes the PNG away at which point it thinks it is hovered again and comes back, and repeat.

Dealing with this seems to require a modification of the HTML, like such:

<a href="…"><span>…</span></a>

The PNG can be shown in the span or the a and there are no hover issues. The CSS is the same as the AlphaImageLoader except the border padding is applied to the span rather than the a.

Combined Form

A combined version that should work in IE and other browsers looks like:

<style type="text/css">
#sidebar { padding-right: 0; }
#sidebar a, #sidebar a span {
  display: block;
}
#sidebar a:hover {
  border: solid black;
  border-width: 1px 0px 1px 4px;
  background-image: url('75_red_alpha.png');
}
#sidebar a span { padding: 10px 30px 10px 15px; }
#sidebar a:hover span { padding: 9px 30px 9px 11px; }
</style>
<!--[if lt IE 7]>
<style type="text/css">
#sidebar a, #sidebar a span { zoom: 1; }
#sidebar #sidebar a:hover span {
  background: none;
  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader
   (sizingMethod=scale, src='75_red_alpha.png');
}
</style>
<![endif]-->

PNGs in Links

Sometimes you would like to have PNGs as the link as well as for the background. This is no problem in a decent browser, but it takes a workaround in IE6. What you actually do is use the filter subsystem to set the PNG with opacity as the background on the containing element and then hide the actual image. The code looks like this:

<span class="link" id="double-o">
  <img src="009.png" alt="009" />
</span>

Then the CSS looks like this:

<!--[if lt IE 7]>
  #double-o {
    width: 91px; height: 22px;
    filter: progid:DXImageTransform.Microsoft.AlphaImageLoader
     (sizingMethod=scale, src='009.png');
  }
  #double-o img { display: none; }
<![endif]-->

Automating PNG Transparency in IE6

Since hiding images and whatnot is tedious and you have to change the structure of the page, it is possible to do it with javascript. It simply removes the source element and sets the background on the actual img element to the filtered PNG.

<!--[if lt IE 7]>
  <style type="text/css">
     img { behavior: url("ie_png_behavior.htc"); }
  </style>
<![endif]-->