CSS selector for hideous table-driven markup - css

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/

Related

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.

If a child has a certain specific value, how to check and make "true" so that hover of the parent yields a result?

Okay, the title is worded terribly, I know. I really don't know exactly how to describe this.
I am editing a "website" but I don't have access to HTML or Javascript or PHP or anything else. Only CSS, and I can creatively manipulate the HTML already presented in the website.
<div id="list">
<table>
<tbody>
<tr>
<td class="td1">blahblahblah</td>
<td class="td1">blahblahblah</td>
<td class="td1">blahblahblah</td>
<td class="td1"><a href="bleach.com">Bleach</td>
<td class="td1">Score: 9</td>
</tr>
<tbody>
</table>
<table>
<tbody>
<tr>
<td class="td2">blahblahblah</td>
<td class="td2">blahblahblah</td>
<td class="td2">blahblahblah</td>
<td class="td2">Naruto</td>
<td class="td2">Score: 10</td>
</tr>
<tbody>
</table>
</div>
So this is basically how it's set up. These are 2 anime, Bleach and Naruto. Naruto's score is a 10, Bleach's is a 9. My goal is to select the parent table of the anime that contains a score of 10 so that I can set up a specific hover animation event using keyframes whenever an anime with a score of 10's table is hovered over.
Now the way this is set up, I don't think there's any way to do it other than manually selecting each anime with a score of 10 by doing something like #list > table > td:nth-of-type(4) a[href*="naruto.com"] though I'm not sure that's relevant. That's how I can select the child, but how do I select the table parent to style it for hover? There must be a way. :(
Appreciate any help you can offer. If you leave a comment within the next day I should be able to respond back immediately.
Thanks.
Please keep in mind, I can not simply give a table a class or id. I have no access to adding or editing anything within the set HTML. So I need to figure out a different method. Also, selecting the table by doing #list table:nth-of-type(n) is not possible because the list of tables will be ever-changing (tables added/removed), can be sorted (altering n), and the sheer volume (we're talking hundreds of tables) etc. which would throw it out of play.
This is not possible using only CSS. You need to select for an attribute at least. There was a proposal for a :content selector for CSS 3, but that didn't end up in the spec. (More info here).
My spirits were not dampened. I figured out a way to do it. By manipulating another td I don't need that's within the table that has a score of 10 and setting it to transparent and positioning it over the entire table, giving it a z-index of 1, and all of the other elements within the table a z-index of 2, I can cause the event on table hover to occur as I wished. :) I'm just posting this here in case anyone ever has a problem like this and this may help them as well.

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).

How to display a table row once per page only?

I am trying to display every odd instance of a table row, however there is another table intervening.
The (simplified) structure is:
<div class="question03">
<table class="trendgraph">
<thead>
<tr class="q3_pageheader">....</tr>
<tr>...</tr>
</thead>
<tbody>...</tbody>
</table>
<table class="datatable">
<thead>...</thead>
<tbody>...</tbody>
</table>
<table class="trendgraph">...</table>
<table class="datatable">...</table>
</div>
For this question, I am calling a 'table set' the set of one table.trendgraph table and one table.datatable:
<!-- this is a set -->
<table class="trendgraph">...</table>
<table class="datatable">...</table>
Two of these sets will fit on a single page. The entire section consists only of the enclosing <div> plus 1 to 6 sets.
The output is actually paged media: pdf via PrinceXML, thus, cross-browser compatibility isn't needed.
The challenge is: I want to show tr.q3_pageheader in the table.trendgraph table only once per page, the first time it appears. This row will occur twice per page.
My css first turns these rows off:
div.question03 > table.trendgraph > thead > tr.q3_pageheader {
display: none;
}
Then I have been trying various things to turn the desired row back on:
div.question03 > table.trendgraph:nth-child(odd) > thead > tr.q3_pageheader {
display: table-row;
}
I can get the first tr.q3_pageheader (only) to display by setting nth-child(1). Curiously, none of the tr.q3_pageheader rows display with nth-child(2) or nth-child(even). All of the tr.q3_pageheader rows display with nth-child(odd).
Note that when I remove table.datatable from the html, then all the nth-child settings work as expected.
I could obviously do work arounds here, such as setting a div around a 'page', or setting a class for the first instance of tr.q3_pageheader. This will be part of a system that will output various numbers of 'table sets'. If possible I would like to solve the issue in html or css only without requiring extra decision making in the backend.
Any help or pointers would be appreciated. Thanks!
Answering my own question with this:
div.question03 tr.q3_pageheader {
display: none;
}
div.question03 table:nth-child(4n+1) tr.q3_pageheader {
display: table-row;
}
I've confirmed this works both in PrinceXML and webkit. Something similar would work in any case where you had a set number of tables per page.

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