Combining CSS descendant and class selectors - css

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/

Related

Targeting nested tables

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 */

Selecting descendants with certain classes that are beneath an element

In css I know you can select elements beneath their parent with the > selector:
#myDiv > p {
line-height: 1;
}
Is it possible to do the same for elements with a certain set of classes beneath that element, eg:
#myDiv > .classA .classB {
line-height: 1;
}
So that any child element with classes .classA .classB will get the treatment?
I've tried this and it doesn't seem to be working, and am not sure if I'm going down the right path or if I'm close.
This is a limitation of CSS that you have to repeat your self by doing
#myDiv > .classA, #myDiv > .classB
as your selector. Most CSS preprocessors can make this less of a challenge to keep things DRY.
Yes, you can - but you have to follow the rules. A space character is also a descendant selector, and that's not what you want. If you want to select all descendants that have both classes, try:
#myDiv > .classA.classB {
line-height: 1;
}

Use Less or CSS to repeat previous sibling's style

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.

CSS: How to target a specific cell inside a table?

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

How to select first and last TD in a row?

How can you select the first and the last TD in a row?
tr > td[0],
tr > td[-1] {
/* styles */
}
You could use the :first-child and :last-child pseudo-selectors:
tr td:first-child,
tr td:last-child {
/* styles */
}
This should work in all major browsers, but IE7 has some problems when elements are added dynamically (and it won't work in IE6).
You can use the following snippet:
tr td:first-child {text-decoration: underline;}
tr td:last-child {color: red;}
Using the following pseudo classes:
:first-child means "select this element if it is the first child of its parent".
:last-child means "select this element if it is the last child of its parent".
Only element nodes (HTML tags) are affected, these pseudo-classes ignore text nodes.
You could use the :first-child and :last-child pseudo-selectors:
tr td:first-child{
color:red;
}
tr td:last-child {
color:green
}
Or you can use other way like
// To first child
tr td:nth-child(1){
color:red;
}
// To last child
tr td:nth-last-child(1){
color:green;
}
Both way are perfectly working
If you use sass(scss) you can use the following snippet:
tr > td{
/* styles for all td*/
&:first-child{
/* styles for first */
}
&:last-child{
/* styles for last*/
}
}
If the row contains some leading (or trailing) th tags before the td you should use the :first-of-type and the :last-of-type selectors. Otherwise the first td won't be selected if it's not the first element of the row.
This gives:
td:first-of-type, td:last-of-type {
/* styles */
}
You can use
table tr td:first-child { css here
}
for First Child and
table tr td:last-child { css here
}
for last Child.

Resources