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.
Related
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/
I am having an issue stylizing a class in the first table while keeping the rest of the tables the same. Let me show an example
<table>
<tbody>
<tr class="a"></tr>
</tbody>
</table>
<table>
<tbody>
<tr class="a"></tr>
</tbody>
</table>
<table>
<tbody>
<tr class="a"></tr>
</tbody>
</table>
So I want the class a of the first table to be different than the rest of the tables. How do I go about doing that?
Thank you for your time.
Edit:
I forgot to mention. I cannot add separate classes on each table. I can only give them all the same class. It is generated that way.
In newer browser you can use CSS3's nth-child():
table:nth-child(1) tr.a{
background-color:#ff0000;
}
This works if this is the 1st child of the parent element (e.g. say that these 3 tables are the children of the body.
You can be also more specific that this is the nth table element using the :nth-of-type() selector.
Please help me with CSS selector.
I need to apply special attributes to the last row in a table, which (row) does'n have specified class, for example class "zzz".
<table>
<tbody>
<tr class="odd">...</tr>
<tr class="even zzz">...</tr>
<tr class="odd">...</tr>
<tr class="even">This one should be selected</tr>
<tr class="odd zzz">...</tr>
<tr class="even zzz">...</tr>
</tbody>
</table>
I'm looking for only pure CSS solution, not javascript one. Please don't suggest :not() pseudo-class, as some browsers do not support it.
Thank you for your help,
--Vadim
Sorry, this is not doable with pure CSS, not even with a selector that only modern browsers support.
I'm not 100% certain i fully understand, but you can use something like
tr:last-child
in your css
I've got a bit of an issue that I'm unsure if it's a browser thing or a CSS3 thing.
I have a datagrid using a standard HTML table:
<table>
<thead>
...
</thead>
<tbody>
<tr class="found">
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr class="found">
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr class="found">
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
I have a jQuery function that is searching the contents of the TD elements. If it's found, it maintains the found class. If it's not found, then it removes the found class and and adds a not-found class. Naturally, not-found just sets display: none
So the search function is working the way I'd like. Classes are being assigned appropriately. However, I'm using CSS pseudo selectors to apply styling to alternate rows.
tr.found:nth-child(even) {
background: #fff;
}
tr.found:nth-child(odd) {
background: #000;
}
This works out great before a search takes place. However, after a search and the not-found class is applied, the pseudo selector seems to apply only to the element rather than the element and the class. Either that, or the pseudo selectors are applied during page load and are left static at that point.
I could go through in my jQuery search and reassign specific even and odd classes, but that gets messy. It wouldn't be that big of a deal, but my column headers are sortable, so I'd have to reapply classes on that event as well creating kind of an inefficient method to do what I'm doing. If data samples get too large, you would likely be able to see the class changes iteratively, something I'm attempting to avoid.
Any solutions to this?
EDIT
As requested, I setup a JSFiddle so you geniuses can toy with it: http://jsfiddle.net/bDePR/
Searching for President or Secretary will yield the behavior.
This is the simplest method I could come up with, use the jQuery :visible selector to find all the visible tr elements (after they have been sorted) then simply apply CSS to alternating ones!
// reset the background
$j('tr').css('background', '#ccc');
$j('tr:visible').each(function(i){
if((i % 2) == 0) {
// apply background to every other one
$j(this).css('background', 'yellow');
}
});
e.g. http://jsfiddle.net/bDePR/1/
Edit:
This, by #amustill does the same but is more efficient/concise
// reset the background
$j('tr').css('background', '#ccc');
$j('.found').filter(':odd').css({ background: 'yellow' });
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?