tags:

views:

211

answers:

2

I'm trying to setup a CSS style to highlight a table cell in a nested table when the table is hovered over.

See sample code below.....

<html>
    <head>
     <style type='text/css'>
     table
     {
      border: solid 1px black;
     }

     table.Content:hover td.ContentIndent
     {
      background-color: #AAAAAA;
     }
     </style>
    </head>
    <body>
     <table class="Content">
      <tr>
       <td class="ContentIndent">Root Indent, could be highlighted when this table is moused over</td>
       <td>
        <table class="Content">
         <tr>
          <td class="ContentIndent">Indent 1 - Should be highlighted only when this table is moused over</td>
          <td>Content 1 - Indent 1 should be highlighted when this table is moused over</td>
         </tr>
        </table>
        <table class="Content">
         <tr>
          <td class="ContentIndent">Indent 2 - Should be highlighted only when this table is moused over</td>
          <td>Content 2 - Indent 2 should be highlighted when this table is moused over</td>
         </tr>
        </table>
       </td>
      <tr>
     </table>
    </body>
</html>

Basically when one of the child tables is moused over, I would like it's indentation cell to be highlighted. It would also be cool if the indentation cells of the parent cells would be highlighted.

Unfortunately, the way it's setup now, the indentation cells from both of the child cells get highlighted, regardless of which table is moused over. I've tried this in Firefox 3.5 and IE 8 and get the same results.

I did find this tutorial and associated demo that does basically what I'm trying to do, except it used nested lists instead of tables. But, when I try to use the > operator (to make the style table.Content:hover > td.ContentIndent) it doesn't work at all. I'm not sure what the difference is.

A: 

The problem is that you are using the "Content" class for the surrounding table as well, so the hover event is triggered for the whole table whenever the cursor enters the parent. Give the parent table a different class (e.g. "Parent") and it will work fine.

A selector like

.Content td

will usually apply to every td below .Content, no matter how deeply nested. The > specifies that the rule be valid for immediate children of the element only and not for deeper nested ones. IE before 7 does not recognize >.

Pekka
Thanks for the input. Unfortunately though, I'm trying to avoid giving the parent table a different class because I'm using a PHP script to generate the table structure. The way it is set up the resulting structure can be any number of levels deep.Is there a way to work around that?
zort15
As far as I know, not without Javascript as @Cletus sketched out.
Pekka
A: 

Well, firstly, if you want to support IE6 you're going to need Javascript of some description because that browser only supports the :hover pseudo-element on anchors (links ie <a> tags).

The other problem is you will need the child CSS selector to do this, which again isn't supported in IE6.

So a non-IE6 compatible version is:

table.Content:hover > tbody > tr > td.ContentIndent { background: #AAA; }

Note the <tbody> element that is implicitly created.

Without the child (>) selector this expression:

table.Content td.ContentIndent { ... }

will grab every indent cell because that is known as a descendant selector and the top-level content table is parent to all of them.

You could work around that problem this way:

table.Content:hover td.ContentIndent { background: #AAA; }
table.Content:hover table.Content td.ContentIndent: background: #FFF; }

The second one basically cancels out that problem by reverting the deeper indents to whatever the normal formatting should be. It's a fairly standard technique to dealing with some IE6 issues that could be solved with a child selector but it's not always possible or practical to revert styles this way.

To support IE6 I would recommend a Javascript library. My preferred option is jQuery, which would involve code like this:

$(function() {
  $("table.Content").hover(function() {
    $(this).children("tbody").children("tr")
      .children("td.ContentIndent").addClass("hover");
  }, function() [
    $(this).children("tbody").children("tr")
      .children("td.ContentIndent").removeClass("hover");
  });
});

with:

td.hover { background: #AAA; }
cletus
Awesome, thanks. The good news is that both CSS versions worked perfectly for what I'm trying to do.The bad news is that when I tried it out in Firefox 3.5, Chrome (not sure what version to be honest), Opera 9.63, IE 7, and IE 8, It worked perfectly Firefox, Chrome, and Opera, but not IE (7 or 8, figures). This is a relatively minor aesthetic enhancement to my site, so I was trying to avoid adding Javascript for it, and if it doesn't work, it's not a huge deal.On the other hand, it's long over due that I should learn some jQuery, so maybe this can be my excuse.
zort15
Always put a DOCTYPE at the top of your HTML document. It forces IE from quirks to standards compliant mode (or as I like to call it from "horribly broken" mode to "mildly broken" mode). Always always use a DOCTYPE.
cletus
Cool, I copied the DOCTYPE from Stack Overflow and it now works perfectly in IE 7 and 8. Thanks for all the help.
zort15