Hosted by the good folks at Ultima Networks
Ultima Networks logo

CSS Remote Rollover

What Is A Remote Rollover?

The visual effect of a remote rollover is that when the cursor is rolled over one part of the document, a change occurs in a remote ( unconnected ) part of the document.

Here's a simple example. Below it is the corresponding HTML and style definitions:

<div id="simplerr">
<a id="simple_link" href="#simplerr">
<span class="area_a">Span Area A</span>
<span class="area_b">Span Area B</span>
<span class="area_c"></span></a>
</div>

================================

#simplerr {
  position: relative;
  width: 230px;
  height: 30px;
  font-size: 16px;
  border: 1px solid #00C;
  margin: 0.5em 0 0.5em 0.5em
}

#simple_link {
  position: relative;
  display: block;
  height: 26px;
  width: 220px;
  border: 1px dashed #F00;
  text-decoration: none;
}

#simple_link span {
  position: absolute;
  margin: 2px;
  border: 2px solid #EEE;
}

#simple_link .area_a {
  top: 2px;
  left: 3px;
}

#simple_link .area_b {
  top: 2px;
  right: 8px;
}

#simple_link .area_c {
  /* For the rollover to work for area_c
     in IE 7, the background must be set,
     or else only the border would trigger 
     the :hover. A transparent 1-pixel image
     can be tiled in the background, or the
     background-color set to a non-transparent
     color value. */
  /* background-image: url(images/spacer.gif); */
  background-color: #DDF;
  border-color: transparent;
  top: 2px;
  right: -350px;
  width: 11em;
  height: 20px;
}


#simple_link:hover .area_a {
  border: 2px dotted #AA0;
}

#simple_link:hover .area_b {
  border: 2px dashed #0DD;
}

#simple_link:hover .area_c {
  font-style: italic;
  border-color: #CC0;
}

In JavaScript these sort of changes are implemented using onmouseOver and onmouseOut event handlers1. Most commercial HTML editors provide some way to implement rollovers by inserting prepackaged JavaScript code2,3. JavaScript is a powerful tool that can do so much more than simple color or image rollovers.

CSS can be used to implement many of the rollover tasks that formely required JavaScript, specifically in the area of menus and tabs. These rollover changes occured to the element directly under the cursor. But we can use the :hover pseudo-class and absolute positioning to produce the effect of changes happening remotely from hovered elements.

The :hover Dynamic Pseudo-Class

:hover is one of three dynamic pseudo-classes, the other two being :active and :focus4. Quoting from W3.Org: The :hover pseudo-class applies while the user designates an element (with some pointing device), but does not activate it. The most common example is when the mouse cursor is over a link but the mouse button is not depressed, which corresponds to a:hover.

Using the a Link Element

The only HTML element that can reliably be counted on to have a :hover state across browsers is the a link element. In the example shown on the left, the three spans to be affected by a rollover are within an a element. Note that it is not required that the value of the href attribute be a URL - a local # anchor will do, as long as the attribute has a value. The display type is set to block - this allows the a element to be used as a relative position reference. A block display also allows for changing the size of the affective link area by using width and height properties - demonstrated in the example by the red dashed outline.

Absolute Positioning

The "remote" part of remote rollover with CSS is achieved by using position: absolute on each of the child elements within the a element that is to be repositioned. In order to use absolute positioning on the child elements, the positioning of the containing parent a element must be set to relative.

The first two span elements .area_a and .area_b are positioned relative to the left and right sides of the #simplerr div, which is the parent of the a element. The third span element .area_c is positioned outside the bounding box of #simplerr by using a negative value for the right selector. Rolling over the area of .area_c shows that it also triggers a :hover event in the same way as rolling over the effective link area within the red outline.

Triggering Changes In Child Elements When parent:hover Occurs

The last three style selectors specify the unique style changes to each child element upon the :hover event. Theoretically any descendent can be selected upon parent:hover.

What About Siblings?

Of the examples of CSS rollovers I have seen online, none have used sibling selectors. Let's try an experiment:

<div id="outline">
  <div id="siblingtest">
    <div class="mainchild">
  This text is within the mainchild div</div>
    <div id="a_sibling">
  Text in a sibling of the mainchild div</div>
  </div><!-- end siblingtest -->
</div>

===============================

#outline {
  border: 2px solid #AAA;
  background-color: #EDE;
  padding: 0.5em;
  width: 18em;;
}

#siblingtest {
  width: 16em;
  height: 3em;
  font-size: 16px;
  /* Do not use a border - causes faulty :hover 
     behaviour in Safari  */
  /* border: 1px solid #00C; */ 
  margin: 0.5em auto 0.5em auto;
  /* Padding disables :hover in Safari */
  /* padding: 0.5em; */  
}

#siblingtest div.mainchild {
  color: #808;
  border: 2px solid #CC0;
  text-decoration: none;
}

#siblingtest div.mainchild:hover {
  color: #000;
}

#siblingtest div.mainchild + div#a_sibling {
  border: 2px solid #0D0;
}

#siblingtest div.mainchild:hover + div#a_sibling {
  color: #F33;
  border: 2px dotted #D0D;
}

/* Mysterious hack for Safari :hover bug */
div#a_sibling *:hover { } 

}
This text is within the mainchild div
Text in a sibling of the mainchild div

Notice that the :hover activation only works when rolling over the mainchild div, and not over the sibling. This makes sense because the sibling div is not contained within the link element.

My CSS reference book5 states that child and sibling selectors do not work in versions of Internet Explorer 6 or earlier. That may limit the appeal of using this method of CSS rollover. In addition, Safari is prone to screw up :hover due to the most innocent of changes.

Everything Changes At The Same Time

An inherent behavior that may limit the use of parent/descendents CSS remote rollovers is that all :hover changes occur to all decendents at the same time. One way to modify this action - at least in appearance - it to set the visibility of a child to hidden in the normal state, and visible in the :hover state. When an element is hidden, a rollover over the hidden element does not trigger a :hover. That is the technique used in the following horse & rider flipbook animation example.

Browser Issues

The examples shown on this page work in the following browsers:

  • Windows 2000 - Internet Explorer 6, Firefox 2
  • Windows XP - Internet Explorer 5.55, 6 and 7, Firefox 2, Opera 9.10
  • MacOS 10.4 - Firefox 1.5 and 2, Safari 2

Special style defintions were needed to work-around issues in various browsers. The hack for Internet Explorer 7 is commented in the code of the first example shown in above. The special styles needed for Internet Explorer 5.55 and 6 are contained in the file css_rr_lte_ie6.css. Microsoft conditional comments are used to load that css file only if the browser is IE version 6 or earlier.

The Safari browser seems to be very touchy concerning :hover and siblings. See the sample code for all the work-arounds and mystery hack I had to use to get the sibling :hover example to work properly in Safari. I had to remove margins and padding from between the child elements, or else the hover wouldn't trigger if the cursor came from the direction of the sibling! Inigo Surguy's work on a similar problem was an inspiration and a starting point for my debugging efforts concerning Safari.

The online information I found most helpful in regards to working-around the various browser problems were references 6, 7, 8, 9 and 10.

Two More Examples

1 2 3 4 5 6 7 8 9 10 11

Roll over the numbers to see the horse & rider

The horse and rider "flipbook" animation on the left uses visibility changes to reveal different stages of a horse's gallop. The CSS file is here.

The anatomy quiz on the right is based in large part on Andy Bud's tutorial on remote rollover. His tutorial was the springboard for my study of CSS remote rollovers. Even the comments are well worth reading. The CSS file for the anatomy quiz is here.


References

  1. Tutorial on “JavaScript image rollovers”, by WebDevelopersNotes.com
  2. “How to create a rollover in Dreamweaver 2.0”, Adobe TechNote 13672
  3. “Creating an Image Rollover” in Microsoft FrontPage, by David Watson
  4. “5.11.3 The dynamic pseudo-classes: :hover, :active, and :focus”, W3.Org
  5. “Cascading Style Sheets: The Definitive Guide, 2nd Edition” by Eric A. Meyer, O'Reilly & Associates
  6. “IE 6 - Pure CSS Popups Bug” by Peter-Paul Koch
  7. “Pure CSS Popups - IE Bug” by Claire Campbell
  8. “pseudo-class, pseudo-element, pseudo-CSS” by Ingo Chao
  9. “Debugging CSS in Internet Explorer - Part 1” by Nicholas Gagne
  10. “Expanding popup menus in pure CSS” by Inigo Surguy