nth-child(odd) not working as expected - css

Why does every row have a red background when I'm using nth-child(odd)?
<div id="ClientTable">
<div class="ClientTableHeaderRow"><span class="ClientTableHeaderColumn">Full Name</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
<div class="ClientTableRow"><span class="ClientName">Umpa Beeson</span></div>
</div>​
#ClientTable {position: relative;
display: table;
margin-top: 20px;
width: 100%;}
#ClientTable:nth-child(odd) {background-color:#FF0000;}
.ClientTableHeaderRow, .ClientTableRow {display: table-row; }
.ClientTableHeaderRow {font-weight: bold;}
.ClientTableHeaderRow span, .ClientTableRow span {display: table-cell;}​
View the jsFiddle
The expected result is every other row to be red. Instead, as you can see, every row is red.
P.S. Umpa is my cat.

You should be setting ClientTableRow class, like so:
.ClientTableRow:nth-child(odd) {background-color:#FF0000;}
Demo: http://jsfiddle.net/gMR2K/4/
EDIT
As also explained by animuson, you need to apply the :nth-childselector to the element itself, not the parent. The name of the selector can lead one to think it will apply the styling to the children of the selected element, when actually the style is applied to n-th child of the selected element, across the whole document.
Also, if you're worried about browser compatibility you can also do this with JavaScript. Here's an example using jQuery.
$(document).ready()
{
$(".ClientTableRow:nth-child(odd)").addClass("redBackground");
}
Demo: http://jsfiddle.net/gMR2K/10/
As stated here by BoltClock: jQuery "polyfills the :nth-child() selector for older browsers anyway."

nth-child applies to the actual element, not its children. #ClientTable is the 1st (and only) child of its parent. Therefore, it has a red background. You need to be applying the nth-child to the elements inside that division.

Is this the result you want?:
http://jsfiddle.net/gMR2K/6/
#ClientTable div:nth-child(odd) {background-color:#FF0000;}

and that only works in the better browsers. IE 8 and below don't get it. But, you can use jQuery to make it work everywhere or (painfully) add a class to the odd rows.

In my case I made a small mistake
.someclassA .someclassB: nth-child(odd){
You can see as above there is one space between someclassB: and nth-child. thats it.. By deleting that space it started working :)

Related

How to select the ID that's before another ID [duplicate]

This question already has answers here:
Is there a "previous sibling" selector?
(30 answers)
Closed 8 years ago.
I'm trying to do a CSS selection.
I want to select an ID that's before another ID selector.
This is the example:
<div id="wrapper">
<div class="aside_left">Left content...</div>
<div class="main_page">Main content...</div>
</div> <!-- end of wrapper -->
My objective is that the main_page stay on the left, and the aside_left change its position to the right.
Both the aside_left and the main_page have the property float:left I can't change the aside_left property to float:right because it is in many pages.
Is it possible to select the ID or CLASS that is before another ID?
My selector should be something like this: select the .aside_left that are before an .main_page
You cant do this with CSS selectors per se.. your best bet is to use something like jQuery's very accessible .parent() method.
You can see here for CSS3 and here for CSS2, this is not present in the current spec.
The speculative design for CSS4 does provide such a selector using a ! operator, but is not presently supported in any browser.
With this in mind, perhaps think about changing the logic behind what you're trying to do- can you not give the altered elements different class names to more easily identify them? Or progress down from your wrapper element?
Or, have a look into the nth-of-type selector, by using:
#wrapper .aside_left:nth-of-type(odd)
See THIS FIDDLE
This will select only the .aside_left elements which are the first child of the #wrapper element. The first child, as in the first in the DOM, as opposed to the first displayed (using float may visually produce results that dont reflect actual DOM positioning in which case you're back to using jQuery).
Only if HTML Structure Cooperates is Pure CSS Possible
I noted in my comment and ExtPro has noted in his answer that such is not possible by pure css, at least under most conditions. However, there is one set of conditions that it is possible. That is if there end up being more child elements of #wrapper in the html when something other than .main_page is present. This would be a very specifc case requirement, and may not match your situation (probably not based off your comment to ExtPro), but if so, then this code works:
#wrapper > .aside_left:nth-last-of-type(2) {
float: right;
}
See an example fiddle here. You see how this requires that there be two elements only in the case that the .main_page is there, and would demand more elements be present if .main_page is not there. So this technically does not key in on .main_page itself, but rather is using the html structure to change a preceding element based off the number of sibling elements present.
in pure CSS you could use display:flex and order , despite position in the flow of .main_page : (hover it to see them both switching sides).
/* using your HTML */
#wrapper {
display: flex;
flex-flow: row wrap;
height:200px;
width:80%;
margin:auto;
}
#wrapper > div {
width:20%;
box-shadow:inset 0 0 1px;
order:2;
}
#wrapper .main_page {
width:80%;
}
#wrapper > div.aside_left {
background:gray;
}
#wrapper > div.main_page:hover {
order:1;
}
live démo at http://codepen.io/gc-nomade/pen/Iywbj see some tips to use it here : http://css-tricks.com/snippets/css/a-guide-to-flexbox/
You could as well reset direction on #wrapper if you style your 2 div as inl'ne-boxes and restore direction on the childs divs

Inaccuracy in nth-last-child selector

Having trouble understanding.
With the following css :
.bloc .field:nth-last-child(2){ ...some values... }
and the following html (well, haml) :
.bloc
.field
.field
.field
.field
.clearfix
The .clearfix div gets counted in the selector, from this I can't get the good .field's div to be specifically styled.
It seems a bug to me, but I might be wrong. The same kind of problem applies for nth-child.
The big misunderstanding here is how filtering using :nth-child() works.
.bloc .field:nth-last-child(2) means:
"select all second-to-last elements that have the .field class that are inside a .bloc".
It does not mean:
"select all second-to-last .field elements that are inside a .bloc".
With this understanding, you could just change your selector to .bloc :nth-last-child(3).
However, the second paragraph of bažmegakapa's answer makes a lot of sense. You should just remove the .clearfix element and use a different float containment technique. The "micro clearfix" is a good choice. Another option is to add overflow: hidden to .bloc.
Simply remove the clearfix div. The :nth-last-child() and :nth-last-of-type() selectors do not work the way you expect. They will not make a distinction on class names (the first does not make a distinction, only counts from backwards, the second only makes a distinction on element type).
There are thousands of clearing techniques and only some of them require adding markup. Simply overflow: hidden or overflow: auto on the container. If you can use :nth-last-child you could also use a clearing technique that employs ::after.
You are selecting an element with that class if it's a :nth-last-child(2).
You could achieve what you really want, if you were using a different type for the .field and .clearfix elements, with :nth-last-of-type().
Try this, seems to be getting the one before .clear for me:
.bloc .field:nth-last-child(2) { color: #CC0000; }​
http://jsfiddle.net/clowerweb/Dp3yW/

How to exclude a class with all children in style definition

I have a file like
<div>
<div class="abc">
<div>
<!--some more divs inside-->
</div>
</div>
</div>
What I want to do is to apply styles only to the first div. I tried to use div:not(.abc, .abc *), div:not(.abc):not(.abc *), div:not(.abc), div:not(.abc) * but none of these worked. It would be hard to edit the html, because there would be many files to be edited. Also the code shown above appears in different places, so using > selector is not the solution... Does someone know how to do this?
You cannot reliably use the :not() selector in CSS for excluding an element and/or its descendants. The reason for it is explained in this answer (and some others that it links to):
You can't use combinators. This works in jQuery, but not CSS:
/*
* Grab everything that is neither #foo itself nor within #foo.
* Notice the descendant combinator (the space) between #foo and *.
*/
:not(#foo, #foo *)
This one is particularly nasty, primarily because it has no proper workaround. There are some loose workarounds (1 and 2), but they usually depend on the HTML structure and are therefore very limited in utility.
And since your markup is unpredictable enough that you cannot edit it or use the > selector, I'm afraid there's not much of a way out for you other than to either find a way to apply a class to your top div and use that class, as demonstrated by Fluidbyte, and/or use jQuery, as implied above.
I usually find it's easier to include what you need via a class then try to exclude descendant elements. See the fiddle here: http://jsfiddle.net/cLtHg/
That takes care of inheritance issues and is much more cross-browser friendly.
If you're really not touching the HTML, then a simple although dirty approach would be to apply styles to the first div and then remove them from subsequent divs, like so:
div {margin-bottom: 20px; border: 1px solid #ccc;}
div div {margin-bottom: 0; border: none;}
The major drawback here is that some styles in the child divs may get removed unintendedly. Depends on how they're styled in the first place.
Use :first-child with the ID or Class of its parent Element. If you are unable to catch the element using CSS, it is suggested to use Javascript or jQuery.
Have you tried :first-child or :nth-child() selecor?

CSS Selecting element after chosen class

I'm modifying JQuery UI Accordion Menu, which currently has a structure as below:
<h3>Title</h3>
<div>Children</div>
<h3 class="no-children">Title</h3>
<div>Children</div>
<h3>Title</h3>
<div>Children</div> ...
As you can see, the middle title has no children, so what I want to do in CSS is something along the lines of selecting the div that occurs after the .no-children class and hide it. These are not nested so I can't do this the easy way.
I know I can display:none but I can't seem to select the correct element.
Is there a way to do this?
.nochildren+div{
/* Style goes here */
}
This selects a DIV that that is immediately preceded by a element with the the .nochildren class. This will only work if both elements are on the same level, many older browsers will have issues with it.
http://www.quirksmode.org/css/contents.html
If you are using jQuery there is an easy way of doing this Here
You could use
$('.no-children').next().hide();
or .nextUntil();
http://jsfiddle.net/lollero/DqpPd/1/
CSS way would be
.no-children + div { display: none; }
http://jsfiddle.net/lollero/DqpPd/ ( ie7+ )

CSS :last-child

I have a div#content with many div.item inside it.
When using :last-child to make the last div.item with no border-bottom, it's OK.
But, as the content is dynamically appended using php and mysql results I'm using a conditional pagination table that will be appended after the last div.item which means at the bottom of the div#content. Here will be the problem as the CSS :last-child will not recognize the last div.item as the last-child.
my CSS looks like:
div#content div.item:last-child {
border-bottom: none;
}
as you can see I'm defining that the last child id such a div.item
Any suggestions please. thanks in advance.
!!!!! Please note that the problem is not in the fact that the content is dynamic but in the fact that the CSS :last-child doesn't recognize the div.item as the last child but the last element in the div#content despite telling the CSS that it's:
div#content div.item:last-child
One possibility I can think of is that you're appending elements that aren't <div>s and/or don't have the item class. Check the output of your PHP/MySQL script and see if there are any non-div.item elements beside (in DOM terms) the div.item elements.
Such elements will not match the selector:
div#content div.item:last-child
That selector finds only <div>s with item class, that are the last child of div#content.
Here's an example.
Before appending
<div id="content">
<div class="item"></div> <!-- [1] Selected -->
</div>
After appending
<div id="content">
<div class="item"></div> <!-- [2] Not selected -->
<div></div> <!-- [3] Not selected -->
</div>
What's being selected, what's not, and why?
Selected
This <div> element has the item class, and it's the last child of div#content.
It exactly matches the above selector.
Not selected
This <div> element has the item class, but is not the last child of div#content.
It doesn't exactly match the above selector; however, it can possibly match either one of these selectors:
/* Any div.item inside div#content */
div#content div.item
/* The last div.item child of its parent only */
div#content div.item:last-of-type
Not selected
Although this <div> element is the last child, it does not have the item class.
It doesn't exactly match the above selector; however, it can possibly match this:
/* Any div that happens to be the last child of its parent */
div#content div:last-child
It seems appending items dinamically does not make the layout engine re-run some CSS rules like :last-child.
I think you can re-read/reload CSS file making the rule apply. Don't know, it's a guess.
Another possibility is dinamically set the styles.
EDIT: It seems you have a CSS x Browser problem.
Check this out: http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28Cascading_Style_Sheets%29#Selectors
you could use javascript to refresh the CSS only. See here: http://paulirish.com/2008/how-to-iterate-quickly-when-debugging-css/
Another approach would be to use a library like jQuery and fire this line of script every time you add new divs. (or maybe you're using another js library, as you say that you are dynamically adding divs to the page)
$('div#content div.item:last-child').css('borderBottom','none');
you might need to reset borders before you do the above though. i.e. the previous 'last' div may still not have the border bottom. so reset all borders then fire the script to remove the border for the last one.

Resources