Is it possible to chain :not() then :last-child? - css

I need to style (CSS only) the last child element while excluding those with a specific class.
For example, I want to style
<ul>
<li>Bar</li>
<li>Bar</li>
<li>Bar</li>
<li>Should have a green background</li>
<li class='foo'>Bar</li>
</ul>
The last li without class 'foo' should be green. I tried
li:not(.foo):last-child {
background-color: green;
}​
or
li:not(.foo):last-of-type {
background-color: green;
}​
but it doesn't works.
See http://jsfiddle.net/gentooboontoo/V7rab/2/

The answer to your question Is it possible to chain :not() then :last-child? (or, more simply, can pseudo-classes be chained?) is very much a yes. But as others have pointed out, if an li:last-child has an id="foo" then nothing will be selected. As a demonstration, a similar expression
li:not(.bar):last-child {
background-color: green;
}​
works just fine. The problem is that successive selectors all apply to the entire context, not to a subset specified by previous expressions so li:not(.foo):last-child is identical to li:last-child:not(.foo), which is clearly not what is required.

I don't think that will work (it doesn't work, but I don't think it should work anyway)
The selector is working, but the second-to-last li is never going to be the :last-child because it isn't the last-child...
It isn't like jQuery's not() method which actually removes the specified element from the selection. The CSS :not selector/filter will ignore the element, but not remove it from the page

There is only one last child inside any element. In your example, it's <li class='foo'>Bar</li>. If you have exact number of children though, you could use adjacent-sibling combinator:
LI:first-child + LI + LI + LI {/* here are declarations for 4th LI. */}

Applying 'last-child' will give browser issue. so I tried in Jquery.
If you need use this code.
var a = 0
$('ul li').each(function() {
$(this).attr("id",a);
a++;
});
var b = a-1;
$('#'+b).attr('style','background-color:green');​

Related

:last-of-type not working correctly [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 3 years ago.
<ul>
<li class="list">test1</li>
<li class="list">test2</li>
<li class="list">test3</li>
<li>test4</li>
</ul>
How do I select the "last child" with the class name: list?
<style>
ul li.list:last-child{background-color:#000;}
</style>
I know the example above doesn't work, but is there anything similar to this that does work?
IMPORTANT:
a) I can't use ul li:nth-child(3), because it could happen that it's on the fourth or fifth place too.
b) No JavaScript.
This can be done using an attribute selector.
[class~='list']:last-of-type {
background: #000;
}
The class~ selects a specific whole word. This allows your list item to have multiple classes if need be, in various order. It'll still find the exact class "list" and apply the style to the last one.
See a working example here: http://codepen.io/chasebank/pen/ZYyeab
Read more on attribute selectors:
http://css-tricks.com/attribute-selectors/
http://www.w3schools.com/css/css_attribute_selectors.asp
You can use the adjacent sibling selector to achieve something similar, that might help.
.list-item.other-class + .list-item:not(.other-class)
Will effectively target the immediately following element after the last element with the class other-class.
Read more here: https://css-tricks.com/almanac/selectors/a/adjacent-sibling/
This is a cheeky answer, but if you are constrained to CSS only and able to reverse your items in the DOM, it might be worth considering. It relies on the fact that while there is no selector for the last element of a specific class, it is actually possible to style the first. The trick is to then use flexbox to display the elements in reverse order.
ul {
display: flex;
flex-direction: column-reverse;
}
/* Apply desired style to all matching elements. */
ul > li.list {
background-color: #888;
}
/* Using a more specific selector, "unstyle" elements which are not the first. */
ul > li.list ~ li.list {
background-color: inherit;
}
<ul>
<li class="list">0</li>
<li>1</li>
<li class="list">2</li>
</ul>
<ul>
<li>0</li>
<li class="list">1</li>
<li class="list">2</li>
<li>3</li>
</ul>
You can't target the last instance of the class name in your list without JS.
However, you may not be entirely out-of-css-luck, depending on what you are wanting to achieve. For example, by using the next sibling selector, I have added a visual divider after the last of your .list elements here: http://jsbin.com/vejixisudo/edit?html,css,output
$('.class')[$(this).length - 1]
or
$( "p" ).last().addClass( "selected" );
I suggest that you take advantage of the fact that you can assign multiple classes to an element like so:
<ul>
<li class="list">test1</li>
<li class="list">test2</li>
<li class="list last">test3</li>
<li>test4</li>
</ul>
The last element has the list class like its siblings but also has the last class which you can use to set any CSS property you want, like so:
ul li.list {
color: #FF0000;
}
ul li.list.last {
background-color: #000;
}

CSS specificity of :not() pseudo class

I have this small HTML:
<div id="column">
<div class="ticker">
<ul>
<li>Item 1</li>
</ul>
</div>
</div>
For ul elements outside of the .ticker class, but inside of the #column id exists this CSS:
#column ul:not(.a):not(.b) {
margin: 1em;
}
But inside the .ticker class I don't want this margin. So I thought I could use:
#column .ticker ul {
margin: 0;
}
That said, I know that the specificity of the first CSS selector is higher because of the two :not() pseudo classes. But to get a higher specificity I had to append those two :not() in the second CSS snippet to the ul, too. So that works:
#column .ticker ul:not(.c):not(.d) {
margin: 0;
}
Isn't that stupid? In fact it doesn't matter what you use in the two :not()pseudo classes. They just have to be there. This doesn't make any sense to me.
Is that simply a part of CSS3 which is not perfect or is there a solution which my brain didn't come up with yet?
See it in action here: http://jsfiddle.net/9BDw5/2/
It's not just you; this is indeed one of the fundamental pitfalls of specificity as a CSS concept.
A simpler solution that is equally valid would be to repeat your .ticker class selector so you have this:
#column .ticker.ticker ul {
margin: 0;
}
This way you do not have to modify your element to add an extra class just for the sake of increasing selector specificity.
The spec verifies this:
Note: Repeated occurrances of the same simple selector are allowed and do increase specificity.
On a side note, remember that the specificity of the :not() pseudo-class is strictly defined (in the same section of the spec) as equal to that of its argument. So :not(#id) and #id have the same specificity, and likewise for :not(E):not(.a) and E.a. The :not portion does not count at all, not even as a pseudo-class.
This limitation in specificity will be addressed in Selectors 4, which enhances :not() to accept a comma-delimited list of selectors. The specificity of a :not() that contains a selector list will be that of the most specific selectors in the list, so the specificity of ul:not(.c, .d) is equal to 1 type selector and 1 class selector, compared to ul:not(.c):not(.d) which is equal to 1 type selector and 2 class selectors. This makes it tremendously useful in excluding any number of classes from a match.
Here is an alternative, and somewhat cleaner approach.
Add a fictitious class name to your div.ticker element:
<div id="column">
<ul>
<li>Outside Item 1</li>
</ul>
<div class="ticker extra-tag">
<ul>
<li>Item 1</li>
</ul>
</div>
</div>
and modify the CSS as follows:
#column ul:not(.a):not(.b) {
margin-left: 1em;
}
#column .ticker.extra-tag ul {
margin-left: 0;
}
So, the specificity of the first rule is 1-1-2 and for the second rule 1-1-2.
The two :not() count as two classes, so you need to have at least two classes in
the second rule, which I implemented by using the fictitious class name .extra-tag.
The fictitious class is probably more computationally efficient than adding the
extra :not() pseudo-class.
See demo at: http://jsfiddle.net/audetwebdesign/7beNx/
Learn more about CSS specificity at: http://www.w3.org/TR/css3-selectors/#specificity
As mentioned above chaining the :not() pseudo-class increases specificity by one each time.
This article explains it very nicely

selector in IE7

I'm using css2 to implement some fixes for IE7 on a website.
So I have to put margin-top:30px and margin-bottom:-30px a <h2> title but I dind't find right selector.
<div class="ui-content">
<h2>Text</h2>
<ul class="ui-listview">
List Items
</ul>
</div>
The fact is that Everytime there is a H2 followed by a UL, I must put those two properties, so I wanted to do a selector with h2 and ul, but I don't know wich ones...
Thanks to help me
You can't select h2s followed by uls but you can do it the other way round. E.g.
h2 + ul { /*your css to style the ul*/ }
So you could put fixes/negative margins or whatever on the ul?
This is a only-ie-7 selector:
IE 7 only
*:first-child+html h2 {}
Anyhow, I don't recommend it because almost no one uses this browser anymore, so neither should you program specially for it.
Everytime there is a H2 followed by a UL, I must put those two properties, so I wanted to do a selector with h2 and ul
As stated by #Spudley and #Coop, you can't select an element that is followed by another element (except rare cases with series of li or td or th and :nth-last-child() but it's more of a trick).
The closest thing you can do in pure CSS is testing if h2 is followed by (an)other element(s) or not, i.e. if it's not alone with :only-child pseudo.
From MDN:
The :only-child CSS pseudo-class represents any element which is the only child of its parent. This is the same as :first-child:last-child or :nth-child(1):nth-last-child(1), but with a lower specificity.
Support is IE9+ so if you want to style this element in IE7 and IE8 too (or in the precise case where it's followed by ul but not p or h3...), you'll need JavaScript or to add a class server-side and style this class.
.ui-content > h2:not(:only-child) {
margin-top: 30px;
margin-bottom: -30px;
}
EDIT:
You can also test if H2 is both the :first-child and the second-to-last child of its parent so it'll be styled if it's followed by whatever element but not if this second element has other siblings (third, fourth one, etc)
.ui-content > h2:first-child:nth-last-of-type(2) {
margin-top: 30px;
margin-bottom: -30px;
}
Simplest code would be ;)
<div class="ui-content">
<h2 class="followed-by-list">Text</h2>
<ul class="ui-listview">
List Items
</ul>
</div>
.followed-by-list {
margin-top: 30px;
margin-bottom: -30px;
}
Other trick that'd mean a complete overhaul of your project (say, for next project ;) ): never set a single margin-bottom to content elements (I mean h2, ul, p, etc. It's OK for div and below "blocks") and always set a margin-top to:
an element (general case) ex: p
if needed, an element coming after another like elt1 + p would have a certain margin-top, elt2 + p another one, etc

CSS Selecting First Child

Im still trying to figure out how to properly use my nth, first, and last child selectors. Thanks for your patience.
If my markup is like this:
<div class="the-wrapper">
<table class="the-table">
<!-- the table -->
</table>
<table class="the-table">
<!-- the table -->
</table>
</div>
How can I select the last <table class="the-table"> to apply a margin?
I thought I could select it like this: .the-wrapper .the-table:last-child { /* css */ } but this does not work. What am I missing? Thank you!
EDIT
Sorry everyone I printed my markup incorrectly... The correct markup is above
The + is used to select "siblings" elements. (siblings in the sense of being childs of the same parent) http://jsfiddle.net/Lhmjq/
You can't use nth-child or last-child for this; as the name say, is for childs, and unless you put a parent, you can't do it.
Here is an example with a parent: http://jsfiddle.net/Lhmjq/2/ In this case, is done with last-child
(updated to your new code)
Here is a tiddle: http://jsfiddle.net/Lhmjq/4/
.the-wrapper .the-table:last-child {
color: blue;
}
Updated with your new code: http://jsfiddle.net/Lhmjq/4/
.the-wrapper .the-table:last-child { /* css */ }
The previous code should select the last table in the wrapper. The targeting for structural pseudo classes can be confusing. The pseudo classes are defined in regards to it's direct parent. For instance, say you have a list of elements:
<ul class="target-me">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
and you want to target the last li in the list. Your CSS would be:
.target-me > li:last-child { color: red; }
You can also use the pseudo selectors to target numbered items from the position in the DOM, say I want to target the second element:
.target-me > li:nth-child(2) { color: red; }
You can also use these pseudo selectors in a selector hierarchy.
.target-me > li:first-child span { ... }
You can also chain pseudo selectors:
.target-me > li:first-child:hover { ... }
In conjunction with a polyfill like Selectivizr you can use these selectors on all browsers. I hope this helps!
Your code ".the-wrapper .the-table:last-child " will return the last-child elements of ALL your ".the-wrapper" classes. What you want to do is select the last ".the-wrapper" element. The code below will select the last-child table of the last ".the-wrapper" element, which is what you are looking for...
$('.the-wrapper .the-table:last-child').last().css("border","1px solid #b5b5b5")
Cheers!

How do I select the "last child" with a specific class name in CSS? [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 3 years ago.
<ul>
<li class="list">test1</li>
<li class="list">test2</li>
<li class="list">test3</li>
<li>test4</li>
</ul>
How do I select the "last child" with the class name: list?
<style>
ul li.list:last-child{background-color:#000;}
</style>
I know the example above doesn't work, but is there anything similar to this that does work?
IMPORTANT:
a) I can't use ul li:nth-child(3), because it could happen that it's on the fourth or fifth place too.
b) No JavaScript.
This can be done using an attribute selector.
[class~='list']:last-of-type {
background: #000;
}
The class~ selects a specific whole word. This allows your list item to have multiple classes if need be, in various order. It'll still find the exact class "list" and apply the style to the last one.
See a working example here: http://codepen.io/chasebank/pen/ZYyeab
Read more on attribute selectors:
http://css-tricks.com/attribute-selectors/
http://www.w3schools.com/css/css_attribute_selectors.asp
You can use the adjacent sibling selector to achieve something similar, that might help.
.list-item.other-class + .list-item:not(.other-class)
Will effectively target the immediately following element after the last element with the class other-class.
Read more here: https://css-tricks.com/almanac/selectors/a/adjacent-sibling/
This is a cheeky answer, but if you are constrained to CSS only and able to reverse your items in the DOM, it might be worth considering. It relies on the fact that while there is no selector for the last element of a specific class, it is actually possible to style the first. The trick is to then use flexbox to display the elements in reverse order.
ul {
display: flex;
flex-direction: column-reverse;
}
/* Apply desired style to all matching elements. */
ul > li.list {
background-color: #888;
}
/* Using a more specific selector, "unstyle" elements which are not the first. */
ul > li.list ~ li.list {
background-color: inherit;
}
<ul>
<li class="list">0</li>
<li>1</li>
<li class="list">2</li>
</ul>
<ul>
<li>0</li>
<li class="list">1</li>
<li class="list">2</li>
<li>3</li>
</ul>
You can't target the last instance of the class name in your list without JS.
However, you may not be entirely out-of-css-luck, depending on what you are wanting to achieve. For example, by using the next sibling selector, I have added a visual divider after the last of your .list elements here: http://jsbin.com/vejixisudo/edit?html,css,output
$('.class')[$(this).length - 1]
or
$( "p" ).last().addClass( "selected" );
I suggest that you take advantage of the fact that you can assign multiple classes to an element like so:
<ul>
<li class="list">test1</li>
<li class="list">test2</li>
<li class="list last">test3</li>
<li>test4</li>
</ul>
The last element has the list class like its siblings but also has the last class which you can use to set any CSS property you want, like so:
ul li.list {
color: #FF0000;
}
ul li.list.last {
background-color: #000;
}

Resources