How to target cell in 2nd row when there's a rowspan? - css

My CSS centers all the cells in a data table, except the cells in the first column are centered, like so:
td {text-align:center}
td:first-child {text-align:left}
That's all fine and good except for tables where any of the cells in the first column span multiple rows. Of course a picture's worth a thousand words, so here you go:
http://jsfiddle.net/michaelbluejay/qmGGG/1/
I know I can use inline CSS or classes on the offending cells to make them centered, but I'm hoping there's a general solution which doesn't require editing the <table> itself. What do you think?

You can use colgroup for that.
http://www.w3schools.com/tags/tag_colgroup.asp
Don't forget to remove your td:first-child selector if you try.
<colgroup>
<col />
<col style="text-align:center;" />
<col style="text-align:center;" />
</colgroup>
I used the inline styles just as an example. Put this in your css file of course.

Related

CSS selector for hideous table-driven markup

JSFiddle: https://jsfiddle.net/dc9wdwem/
I inherited a legacy application that some clients are still using and expecting upgrades for. One recent upgrade "broke" the existing CSS and the easiest way to resolve it is to "un-break" just one little table.
The markup is nested table upon nested table. But for the sake of stripping down to the bare essentials, here's the barest version of where to find my table.
<div id="someId">
<table>
<tr>
<td>
<table>
<tr>
<td>
<table> <!-- not this table --> </table>
</td>
<td>
<table> <!-- THIS ONE!! --> </table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
There are other tables and rows and cells scattered throughout, but this structure gets you there.
Using the "direct descendant" symbol is tricky because the tables are descended within rows and cells as well as other tables. So table>table>table isn't going to do it. But then if you go with a general descendent selector, you end up selecting too many things table table table will get you a whole bunch of tables. Here's the closest I got so far:
#someId>table table td:nth-child(2) table {
background-color: red;
}
I would normally be glad to add even more > selectors; however, I believe the browsers themselves are filling in tbody elements and so forth and I don't know that I can reasonably predict that the proper structure will always be intact. The above selector is selecting more tables than the one I'm trying to isolate.
None of the nested tables have IDs or classes, and nor do I have the opportunity to add them in. The upgrade process does not upgrade the customer's markup, which they may have themselves partially customized over time.
Anybody have any CSS selector magic that will work, assuming the above markup alongside browser-filled elements like tbody?
This will work for the specific HTML in your fiddle:
#someId>table table:nth-of-type(1) td:nth-of-type(2) table {
background-color: red;
}
Obviously, if the HTML changes in pretty much any way, this is probably not going to work.
You missed a Table in your css.
try:
div#someId > table table table td:nth-child(2) > table
https://jsfiddle.net/ba52Lwkg/
#someId > table table:first-of-type td + td > table
this should work.
https://jsfiddle.net/dc9wdwem/

Can and should a style sheet style every element in this HTML?

I'm developing a CMS plugin that generates HTML. I want to let users style the HTML any way they want. Here is the HTML:
<div id="ss:">
<table>
<colgroup>
<col span="1">
<!-- span can range from 3 to 6. -->
<col span="4">
<col span="4">
</colgroup>
<thead>
<tr>
<th rowspan="2">Variable text goes here</th>
<!-- span can range from 3 to 6. -->
<th colspan="4">Responses</th>
<th colspan="4">Percentage</th>
</tr>
<tr>
<!-- this row could contain from 6 to 12 headings -->
<th>Small</th>
<th>Med.</th>
<th>Large</th>
<th>Tot.</th>
<th>Small</th>
<th>Med.</th>
<th>Large</th>
<th>Tot.</th>
</tr>
</thead>
<tbody>
<!-- one more more rows with this structure -->
<tr>
<th>1. What size Coke do you prefer?</th>
<td>24</td>
<!-- largest number surrounded by strong tags -->
<td><strong>28</strong></td>
<td>0</td>
<td>52</td>
<td>46</td>
<!-- largest percent surrounded by strong tags -->
<td><strong>54</strong></td>
<td>0</td>
<td>100</td>
</tr>
</tbody>
</table>
</div>
I've placed the HTML inside div with an ID to allow users to select only elements within it. So my questions are:
Can a stylesheet style every element here without using classes, even if that means using pseudo-classes like nth-child?
Would that be a good practice? If not, what is a good strategy?
I could actually generate a class for every element, but where's the line between that's good and that's crazy?
Can a stylesheet style every element here without using classes, even if that means using pseudo-classes like nth-child?
Absolutely. There are many ways to target elements. You would have to use nth-child once you get to all the td, th and trs.
#ss:,
table,
colgroup,
col,
[span="1"],
[span="4"],
thead,
tr,
th,
[rowspan="2"],
[colspan="4"],
tbody,
td,
td strong {
// css
}
Would that be a good practice? If not, what is a good strategy?
The argument against using nth-child is that the browser has to process every child element to do the math and find the correct elements, but with using classes or ids it can find the correct elements easier. So it's easier for the browser to process the css targeting classes and ids. I just read about browser processing nth-child this week, but I couldn't find the article for reference. I'm a big fan of this CSS Tricks page for nth-child references
I could actually generate a class for every element, but where's the line between that's good and that's crazy?
Everyone has their own definition of crazy. Giving rows a class would be helpful, then let the user get into the nth-child depth.`
Why do you need IDs or classes? Just target the elements themselves
h1 {
...
}
h2 {
...
}
h3 {
..
}
etc...
You can target your stylesheets dynamically like in this SO post.
Also for the record, DOM look-ups by class are significantly faster than by ID. A quick Google search on that will tell you more than I ever could.

Can I combine pseudo-classes in CSS like this?

HTML:
<table>
<tr class="not-counted"><th>Heading 1</th></tr>
<tr><td>key1</td><td>val1</td></tr>
<tr><td>key2</td><td>val2</td></tr>
<tr class="not-counted"><th>Heading 2</th></tr>
<tr><td>key3</td><td>val3</td></tr>
</table>​
CSS style:
table tr:not(.not-counted):nth-child(even) td {
background-color: gray;
}​
Demo: http://jsfiddle.net/MartyIX/fdtpL/
I hoped that TR containing key3 would have grey background too but it does not work. How to write the CSS properly?
Thanks!
You want to style in CSS a table with zebra rows with an unknown number of rows not styled (or hidden, same result), these unstyled rows being at any position in the table.
Each remaining row to be styled is preceded by an unknown number of unstyled rows at odd position and an unknown number of unstyled rows at even position in whatever order.
Your particular need isn't stylable in CSS2.1 or CSS3, unless you add a constraint.
By example, if you know how much unstyled rows you could encounter, than the 2 fiddles in my following twit will do the trick: https://twitter.com/#!/PhilippeVay/statuses/166243438436687873 This is CSS from hell, don't ever do that in production! As briefly stated, jQuery/Sizzle and its pseudo :visible would be far superior. Or even better, add a class server-side to each row you want to style.
Other fiddle with your example: http://jsfiddle.net/yBKqy/
You can see that it works till the row next to your second unstyled row. The remaining rows below are both preceded by an odd unstyled row and an even unstyled row; the rule that apply will be the last one declared. AFAIK no way to apply one or another in a meaningful way. If you add weight to the first selector, it'll always apply. If you don't the last one will always apply.
If you know how much rows can follow an unstyled row before there's another unstyled row or the end of the table, here's another fiddle: http://jsfiddle.net/yBKqy/3/
This particular example works with no more than 4 rows in a row but not 6. You can make it works with 6 but it'd fail with 7, etc
I solved the problem with the help of dummy lines:
HTML
<table>
<tr><th>Heading 1</th></tr>
<tr style="display:none;"><th></th></tr> <!-- dummy line -->
<tr><td>key1</td><td>val1</td></tr>
<tr><td>key2</td><td>val2</td></tr>
<tr><th>Heading 2</th></tr>
<tr style="display:none;"><th></th></tr> <!-- dummy line -->
<tr><td>key3</td><td>val3</td></tr>
</table>​
CSS
table tr:nth-child(even) td {
background-color: gray;
}​
Demo
http://jsfiddle.net/MartyIX/fdtpL/3/
I'm not really proud of it but I've lost too much time with that.

strange IE8 css issue

I have a header row which has this structure:
<th...
<a...
<span...
{text}
If you look at the attachement, you will notice that all the headers with this structure are aligned.
Well, when a specific header is clicked for "sorted" status, the structure will be like:
<th...
<a...
<span...
<table>
<tbody>
<tr>
<td>
{text}
</td>
<td>
<div> //with a background image
</td>
</tr>
</tbody>
</table>
Well, in IE8 this sorted column is no longer aligned (see the screenshot please).
I've tried a lot to put some css style (position:relative, etc) to the table inside the span to fix the alignment in IE8 but I failed..
Is here any css guru which can suggest a fix?
Please note that I can NOT change this structure (its some generated code from ICEfaces library) but I can apply css attributes (if I know where...).
Also, there is no css difference (some specific important style) to the sorted column applied. Just plain table inside that span.
Thanks.
Check the vertical-align property, maybe. Here, judging by the screencap, it seems to be in default mode, 'baseline'. (I'm not sure it will do much, though)
Try :
th.stuff {
vertical-align:top;
}
or :
th.stuff {
vertical-align:middle;
}
Also you could make all th slightly higher and gain somme padding to align the content. I think the problem, overall; commes from the select that appears in the th, inside the table.
You can use IE specific style sheets. They are known as conditional style sheets.
http://css-tricks.com/132-how-to-create-an-ie-only-stylesheet/
The idea of course would be to change the CSS for that element for IE only (because it does work already with other browsers).

What is the proper CSS way to implement right-aligned text on table columns?

To my surprise I just found out that applying text-alignment to a table column is fairly bad supported in current browsers. Neither Firefox 3.5.2, Safari 4.0.3 or IE8 shows the "amount" column below as right aligned.
HTML:
<table class="full_width">
<caption>Listing employees of department X</caption>
<col></col>
<col></col>
<col></col>
<col class="amount" width="180"></col>
<thead>
<tr>
<th>Name</th>
<th>Phone number</th>
<th>Email</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>+45 2373 6220</td>
<td>john#doe.com</td>
<td>20000</td>
</tr>
</tbody>
</table>
CSS
.amount{
text-align: right;
}
Why isn't this working? Also I tried (via firebug) to turn off Firefox' native rule that left-aligns TD elements, but that didn't work either.
I can see that setting background color rule in the amount css class actually works. So I know that the .amount class is applied to all columns:
CSS
.amount{
text-align: right;
background-color: aqua;
}
The CSS 2 spec apparently says that only four attributes are supported by col element -- see Why is styling table columns not allowed?
Criteria for selecting the best solution: must be supported fairly cross-browser (not necessarily in IE6 where I could live with using jquery or a conditional comment to include a specific solution). Also, I expect to apply multiple classes multiple different columns (ie. class="amount before_tax")
I'd hate to set classes on the relevant td in each row. What are my options?
I'd hate to set classes on the
relevant td in each row. What are my
options?
That would be it: class on each td.
If you don't want to add the class to each cell in a column manually, your only other option is to use javascript to do it.
With jQuery:
$("table tbody tr td:eq(3)").addClass("amount");
You can always set a class on on the last element in a row:
.full_width td:last-child {
text-align: right;
}
you have to set the class on the td elements. I think that's the only way.
Your answers got me thinking about creating a JQuery script that parses COL elements. Then it should find each row matching the corresponding COL and apply the COL class to each element like so:
enter code here$("table tbody tr td:eq(3)").addClass("amount");
But only do it, (as a performance improvement), if the class definition contains a text-align in it.
Of course, a full complex implementation of colspan and COLGROUP elements will be overkill and most likely not supported.
Any thoughts on that idea?

Resources