Forum Moderators: not2easy

Message Too Old, No Replies

Break TABLE/TD inheritance

break table td inheritance

         

Dabrowski

5:07 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I have a TABLE. It has some TD's. Well duh?

My CSS says TABLE#one TD { border-bottom: 1px solid black; }

I then put a TABLE inside my TD. All it's TD's inherit the border.

ok, that's fine, but what's the easiest way to break this inheritance and make the nested TABLE revert to default?

Dabrowski

5:09 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I should tell you my current solution:

TABLE#one TD TD { anti-css of the first table }

Which works but isn't exactly what I had in mind.

Robin_reala

6:33 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, you’re using the descendent selector (a space) in your CSS so yes, the only way to kill the inheritance for nested tables is to reset it back to the default.

The alternative would be to use a child selector which would select only the top level <td>s, but won’t work in IE5 or 6:

table#one>tr>td { border-bottom: 1px solid black; }

or, if you’re using XHTML:

table#one>tbody>tr>td { border-bottom: 1px solid black; }

On a different note, are you sure you need to use nested tables? They can pose a fairly severe accessibility issue.

Dabrowski

6:42 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I would use the > selector, if it worked in IE 6 at least.

Yes I do need to use the nested table. What accessibility issue?

Robin_reala

6:52 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Basically it boils down to a difficulty for screen reader users in navigating the structure of your page. A single table linearises OK, nested ones progressively less so.

Dabrowski

7:02 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Oh I see. No that's not a problem at all in this case. The problem I am having is overriding the parent TABLE's CSS.

If the nested TABLE has a different ID selector shouldn't it override? e.g.:

TABLE#one TD { background: red; }
TABLE#nested TD { background: blue; }

Robin_reala

7:11 pm on Apr 9, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, as they both have the same specificity then the second selector will trump the first one.

Dabrowski

3:54 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Robin, thanks for that. I now have a strange problem which I hope you can put your finger on 'cos I can't.

Using that advice I made my nested table. The inheritance does NOT break. The top table has a border-bottom, the nested table shouldn't but still does. Even more annoyingly I made a test page which WORKS! So, here is the code that works, you might want to replace the indents to see it properly:


#one TD {border: 1px solid black;}
#one TR.title { font-weight: bold; }

#two { border: 1px solid blue; }
#two TD {border: 0;}

<table id='one'>
<tr class='title'>
<td>Cell 1</td>
</tr><tr>
<td>
<table id='two'>
<tr><td>Cell 2</td><td>Cell 3</td></tr>
</table>
</td>
</tr>
</table>

The 2 cells in table 1 have a black border, fine. Table 2 has it's blue border, and the cells have none, also fine. Great.

Now the code that doesn't work (I've cut out the irrelevant bits):


TABLE#pagelayout { width: 100%; height: 100%; }
TABLE#pagelayout TD { border-bottom: 1px solid black; }
TABLE#pagelayout TR.title { height: 100px; background: lightblue; }
TABLE#pagelayout TR.title TD { padding: 1.5em; }
TABLE#pagelayout TR.navTR { height: 3em; background: lightcyan; }
TABLE#pagelayout TR.navTR TD { padding: 0.5em 1.5em; }
TABLE#pagelayout TR.footer { height: 9%; background: gainsboro; }
TABLE#pagelayout TR.footer TD { padding: 0; text-align: center; }

TABLE#info { background: lightblue; border: 1px solid blue; }
TABLE#info TH { font-weight: bold; }
TABLE#info TD { border: 0; }

<table id="pagelayout">
<tr class='title'><td>Text</td></tr>
<tr class='navTR'><td>Text</td></tr>
<tr>
<td>
<div class='container scroll'>
<div id='screenstuff'>
<table id='info'>
<tr><th></th><th>Width</th><th>Height</th><th>Aspect</th></tr>
<tr><td>Screen</td><td>#*$!</td><td>#*$!</td><td>#*$!</td></tr>
<tr><td>Client Area</td><td>#*$!</td><td>#*$!</td><td>#*$!</td></tr>
</table>

</div>
</div>
</td>
</tr>
<tr class='footer'><td>Text</td></tr>
</table>

Again you'll want to indent it. As you can see by the nested table's content this is JS generated, but that's a copy of the markup it generates.

Please please find the error!

Fotiman

5:20 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I tried your non-working example and it worked for me. Worked in both IE6 and Firefox 1.5. That is, I don't see a border under the individual cells on the inner table (which I think is what you meant).

Dabrowski

5:53 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Fotiman you're right, I just pasted that into my blank test file, and it also worked. I am truly stumped on this, the only other code that should pertain to this table is:


* { margin: 0; padding: 0; border: 0; }
TABLE { border-collapse: collapse; }

The only other difference is the nested table is written by JS and inserted after the page has loaded, but other styles still apply so I don't think this is it. I also tried that in my test file anyway.

Can I send you a URI so you can have a proper look at the full code?

Fotiman

6:40 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Sure, drop me a sticky mail. :)

Fotiman

6:57 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ah, this is an easy one.

Both of your rules have the same specificity. Therefore, whichever is defined LAST will be the one used. In your case, you are defining the rules for your inner table first in your CSS source, and then defining the rules for the outer table after that. Since they have the same specificity, the one defined later in the source code will get used.

To fix this, just move the rules for your inner table below the rules for your outer table. Alternatively (and probably a better option), you could increase the specificity of the inner table rules so that it will be "more specific". For example, instead of this:

TABLE#info { background: lightblue; border: 1px solid blue; }
TABLE#info TH { font-weight: bold; }
TABLE#info TD { border: 0; }

You could do this:

TABLE TABLE#info { background: lightblue; border: 1px solid blue; }
TABLE TABLE#info TH { font-weight: bold; }
TABLE TABLE#info TD { border: 0; }

Thus, any table with the id of info that also has a table anscestor will have rules of higher specificity, so it won't matter where they are placed in the CSS file.

Hope that helps.

PS- Here's the part in the CSS spec that talks about specificity:
[w3.org...]

[edited by: Fotiman at 6:58 pm (utc) on April 11, 2007]

Dabrowski

7:13 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for your speedy reply Fotiman!

I can't believe it was that simple, I didn't realise CSS accounted for order of definition. I have read the basics on the specs, but more than a few paragraphs I have to admit I tune out.

Using this, if I did this:

TABLE TABLE TD { basic TD defaults }

Would it then set a precedent for any nested table in any order? Obviously this would go at the top of the CSS?

Fotiman

7:28 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Using this, if I did this:

TABLE TABLE TD { basic TD defaults }

Would it then set a precedent for any nested table in any order? Obviously this would go at the top of the CSS?

Yes it would... however, that rule has a very low specificity.

0,0,0,3

A rule that uses an id like:

TABLE#pageLayout TD

will have a specificity of:

0,1,0,2

Which is a much higher specificity, so it would override your generic rule. That means that even nested tables would use the rules defined by this style because it has a higher specificity.

Dabrowski

8:52 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks Fotiman. If only the W3C could explain things in sci-fi everyone would understand it more.

I see now that my 3 storm troopers are no match for a sith, so I modify my scenario as follows:

TABLE#pagelayout would always be the root, so really any table would be nested inside this, so

TABLE#pagelayout TABLE TD { defaults }

would be the answer? As now we have our sith and 3 storm troopers on the same side?

SuzyUK

9:26 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



now you're talking the language ;)

this is the bit where the ID (your sith) truly comes into its own - BUT! although specificity is one of my favourite topics you do know what CSS stands for?

the C in CSS stands for "Cascading" so that should be your first point of attack use the Cascade, i.e. apply the styles in order of the cascade start at the top and work down .. you should only need to use specificity if there is no other way to target your prey (e.g. a cms or a template file has set defaults) . If you then discover like this thread suggests that you need to "lock on" to a target then ID will be your friend

Dabrowski

9:50 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I did know it was cascading, but didn't realise selectors carried different priorities. I thought they were just different ways of addressing stuff.

Unfortunately, you can read as many specs as you like but this doesn't teach you how to actually use the stuff in real life. I came to the conclusion that you give everything an ID, and use classes below that. I assume from this exercise this is not a good way to do it.

If I use 'TABLE#pagelayout TABLE TD' Then I can't override with 'TABLE#info TD' cos I've not got enough storm troopers.

So, ignoring the CSS I already have, how would you use the selectors to get over this problem? I basically want any TABLE inside the #pagelayout to reset to some defaults, in this case removing the border, but then can be overridden as normal.

Robin_reala

9:57 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Best thing to do with CSS (as with anything) is to keep it simple:

#pagelayout td { border-bottom: 1px solid black; }
#pagelayout td td { border-bottom: 0; }

One sith and two stormtroopers narrowly beat one sith and one stormtrooper, causing <td>s within <td>s (nested table situation) to reset to no borders.

Dabrowski

9:59 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I was really trying to find a universal fix, but I don't think there is one. I'll go with that method of un-cssing further TD's. It's just a bit more css but no worry, at least it's tidy.

Dabrowski

10:00 pm on Apr 11, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks for all the input and explanations, I have learnt from this one!