Question
Is there a clean way to apply a style for all sibling elements between two HTML elements?
Background
I have a table with bootstrap's .table-striped class, however, I want an arbitrary number of rows to be striped together as a group. My solution was to create a custom element using
document.registerElement("seq-tr");
and extend the tr:nth-child(odd/even) to tr:nth-of-type(odd/even), as well as to ...tr:nth-of-type(odd/even) + seq-tr:
.table.table-striped {
> thead, tbody, tfoot {
> tr {
~ seq-tr > td {
border-top: none;
padding-top: 0;
white-space: nowrap;
}
&:nth-of-type(even) {
&, + seq-tr {
background-color: #table-bg;
}
}
&:nth-of-type(odd) {
&, + seq-tr {
&:extend(.table-striped > tbody > tr:nth-child(odd));
> td:extend(.table-striped > tbody > tr:nth-child(odd) > td) {
}
}
}
}
}
}
Aside: Originally I had tried using the ~ selector instead of +, but that applied both :nth-of-type(even) and :nth-of-type(odd) to every <seq-tr> after the second row and whichever was later in the compiled CSS file took precedent, rather than being smart about it and looking for whether the closest sibling <tr> was even or odd.
So the above code works for the first <seq-tr> element, but for the following <seq-tr>s, it does not.
Is there a clever way to make this work for any number of consecutive <seq-tr>s?
I could use a seq-tr.striped class, but I would rather not.
Edit
It just occurred to me I could simply use multiple <tbody> elements, and style the rows based on even/oddness of those, rather than the rows themselves.
Can we have multiple <tbody> in same <table>?
I'd still like the answer to my question for other purposes, but it's less pressing now.
Related
I have a table inside of a table, a really simple one.
What I wanted to do is to avoid having border-bottom of td tag in the last row (tr) of the table. What I did is this:
tbody tr:last-of-type td { border-bottom: none; }
I was thinking that this is it, but then I checked the last row of not nested table and the whole nested table was not having a bottom border. Is there a way to avoid this using simple CSS without classes etc.?
To achieve no border bottom of the nested table, you can do so like so:
tbody table td {
border-bottom: none;
}
Note - the above rule makes assumptions about your CSS, which you haven't shared with us. Due to you not including the CSS that applies the border in the first place, it is possible the above won't work due to CSS specificity.
For example, if your rule that adds border to the table is:
tbody tr td {
border-bottom: [whatever style];
}
Then, the selector you need to use to remove the nested table border is:
tbody tr table td {
border-bottom: none;
}
Add your CSS, and we can more accurately answer your question. Or, better yet - read the CSS specificity article, and you'll know how to alter the selector yourself!
I'd say the simplest way is to use class and id. Like so:
table.outer { some: style; } /* class */
table#inner { some: style; } /* id */
But as you said, AVOID classes, then perhaps call the table nested within the table like so:
table { some: style; }
table table { some: style; } /* override outer table */
I'm not well versed in CSS, but I understand the basic idea of specificity (or so I think). Recently I was trying to override the table CSS of Bootstrap 3, which was defined for each cell like so (this is a partial bit, the part that was effective on the inspected element):
.table > tbody > tr.danger > td, .table > tfoot > tr.danger > td {
background-color: #ddd;
}
I was trying to override the background color of the entire row that contained that cell, with this:
table#results > tbody > tr.highlighted {
background-color: #ffd15b;
}
Which, as I understand it, has higher specificity due to the ID. However it wasn't working at all, until I introduced the child td in my CSS:
table#results > tbody > tr.highlighted > td {
background-color: #ffd15b;
}
Why didn't my first attempt work? I tried in both Safari and Chrome (latest versions)
Your problem is not CSS specificity, but merely the background of the cell ( <td> ) hiding the background of the row (<tr>) behind it.
Try adding border-collapse property to the parent table like below
table#results { border-collapse: collapse;}
I am trying to change the background-color of rows that contain my found class in a striped bootstrap table. It works for even rows because bootstrap doesn't have a background color for them, but odd rows I am blocked by bootstraps CSS.
Bootstrap CSS:
.table-striped > tbody > tr:nth-child(odd) > td,
.table-striped > tbody > tr:nth-child(odd) > th {
background-color: #f9f9f9;
}
Custom CSS:
tr.found{
background-color:#CECBCB;
}
How would I override bootstrap's CSS for only a single row at a time (as you can see in demo, odd rows are not overridden)?
BOOTPLY DEMO
Write specific selector to override the bootstrap ones
table.table.table-striped tr.found td {
background-color:#CECBCB;
}
Demo
Also, not only specificity matters here, make sure you apply the background to the td element and not the tr because bootstrap is applying to the td element so even if you apply the background to tr won't make sense.
As you said that you wanted the explanation for the selector I wrote, so here it goes, let us break that and understand..
Starting off with this
table.table.table-striped - Over here am selecting a table element having classes .table AS WELL AS .table-striped
Going further with the selector, tr.found we select the tr elements having a class called .found and lastly, we select the nested td elements.
.table-striped>tbody>tr:nth-child(odd)>td,
tr.found{
background-color:#CECBCB;
}
In addition to Mr. Alien's solution, I found that the following works in Bootstrap 4 without explicitly overriding the table style.
tr.found td{
background-color:#CECBCB;
}
Bootply Demo
Is there a convenient way to combine descendant selectors for a class that doesn't clutter the space much?
For example, I have two rules:
.details-recommendations-table th:nth-child(1) { /*rule*/ }
.details-recommendations-table td:nth-child(1) { /*rule*/ }
as the rules are the same, and describe some td and th elements within a class, it would be handy to combine them into one. Currently, I have
.details-recommendations-table th:nth-child(1), .details-recommendations-table td:nth-child(1) { /*rule*/ }
but that just clutters the space by repeating the name of the parent class. Is there a neat way to combine these rules, something along the lines of:
.details-recommendations-table th:nth-child(1), td:nth-child(1) { /*rule*/ }
The above doesn't work as the td:nth-child(1) part propagates to other tables, i.e. it doesn't apply only to td elements within the .details-recommendations-table class, as intended.
Assuming your td and th elements are validly placed within a tr element, you can simply condense your selector to:
.details-recommendations-table tr :nth-child(1) { /*rule*/ }
If, however, you're wanting to pull the first of each type (regardless of which nth child they are), you can use:
.details-recommendations-table tr :nth-of-type(1) { /*rule*/ }
JSFiddle demo.
In both cases this assumes that your td and th elements have no children. If they do have children, you should introduce a child combinator (>):
.details-recommendations-table tr > :nth-of-type(1) { /*rule*/ }
This will select any first child right beneath the tr:
.details-recommendations-table tr>*:nth-child(1) { /*rule*/ }
I've tested and fixed it now, according to the comment left by BoltClock's a Unicorn:
.details-recommendations-table :not(tr):not(tbody):nth-child(1) { /* rule */ }
Demo: http://jsfiddle.net/Ym9Va/
I have a dynamically generated table and I need to style differently the 5th cell from the first row of that table.
I´m able to style the first row via:
//table.css
.mytable tbody tr:first-child { whatever styles I define.. }
Or the 5th column via:
.mytable tbody td:nth-child(5) { whatever styles I define.. }
I tried to combine this two selectors so that the cell in the 1st row, 5th column is different but without success. How can I achieve this?
You can simply use the below selector
Demo
Demo 2 (Multiple Rows)
.mytable tbody tr:first-child td:nth-child(5) {
/* Styles goes here */
}
Explanation : The above selector selects 5th td element which is nested under 1st tr element which is further nested under tbody which is further nested under ANY element having class .mytable but obviously, tbody will be used inside a table but if you want to make it specific, you can change this .mytable to table.mytable
Or you can use
.mytable tbody tr:nth-child(1) td:nth-child(5) {
/* Styles goes here */
}
Explanation: Same as above, using nth instead of first-child