Why this :not() instruction isn't working? [duplicate] - css

This question already has answers here:
Is the CSS :not() selector supposed to work with distant descendants?
(2 answers)
Closed 7 years ago.
I try to select all lis in the page except whose are inside a container(ascendant) with class .foo
Output: The li 22 should not be colored.
I can't use direct descendants because there could be nested lis and uls.

It's not working because you haven't specified that it's that exact element that can't have the class. The ul element that contains the li element doesn't have that class, so that matches the :not(.foo) part of the selector.
Make sure that the :not(.foo) part applies only to the right element, for example by specifying exactly where the element is in relation to the list element:
:not(.foo) > ul > li { background: red; }
<ul>
<li>11</li>
</ul>
<div class="foo">
<ul>
<li>22</li>
</ul>
</div>

I guess css selectors are using an OR or ORELSE relation. So when you use a selector like :not(.foo) li something similar happens:
statement1: In first place it will check: is actual element's tagname is li? (true)
statement2_1:In second place it will check: is closest parents class not .foo? (true)
statement2_2:In next place it will check next parent: is next parent class not .foo (false)
Theoretically the following statement evaluates:
statement1 AND (statement2_1 ORELSE statement2_2)
true AND (true ORELSE false) => true AND true = > true
What if you just try other way:
li{
background-color: red;
}
.foo li{
background-color: initial;
}
<ul>
<li>11</li>
</ul>
<div class=foo>
<ul>
<li>22</li>
</ul>
</div>

Related

ignoring rows using :not() and styling with nth-of-type odd & even [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
Closed 6 years ago.
I'm wanting to style li's with alternative backgrounds. The pattern should go red > blue > red > blue etc.
The problem is I'm using a :not selector to ignore the first row in one list, and because of that the pattern for that list starts at blue > red > blue. I understand why that is but I'm wondering if it's possible to have the :nth-of-type() odd and even ignore the rows from it's calculations? Or if there is a work around without adding extra markup to my html.
http://jsbin.com/kusolecudo/edit?html,css,output
I do not want to apply any extra markup to my HTML or duplicate my CSS for the :not list.
li:not(.head):nth-of-type(odd)
{ background: red }
li:not(.head):nth-of-type(even)
{background: blue }
ul {width:40%;display:inline-block;list-style:none}
<ul>
<li class="head">
test
</li>
<li>
test
</li>
<li>
test
</li>
</ul>
<ul>
<li>
test
</li>
<li>
test
</li>
<li>
test
</li>
</ul>
While there is no way to have the :nth-of-type() skip based on the result of :not() and basically pretend it's not there, you can achieve what seems to be your intention by adding three more definitions using general siblings selectors.
CSS:
li:nth-of-type(odd)
{ background: red }
li:nth-of-type(even)
{background: blue }
li.head
{ background: none; }
li.head ~ li:nth-of-type(1n+2)
{ background:red; }
li.head ~ li:nth-of-type(2n+3)
{ background:blue; }
ul {width:40%;display:inline-block;list-style:none}
The li.head ~ li will select any li's after the .head one and then you can apply the "odd"/"even" styling with an offset: 1n+2 and 2n+3.
Here's a JSFiddle for reference: https://jsfiddle.net/rjschie/b538upum/
I hope that helps!

: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;
}

Selecting subsequent and preceding elements of a given element via CSS?

If I have a list:
<ul>
<li>item</li>
<li class="selected">item</li>
<li>item</li>
<li>item</li>
</ul>
Is it possible to select the 3rd and 4th items in this list via CSS? And more generally, all items that come after/before the .selected item?
To select the succeeding elements, you would use the general sibling combinator, ~.
Despite not being able to select the previous sibling elements, you could solve this by styling all the elements to begin with, and then overwriting the styling by selecting the succeeding elements.
EXAMPLE HERE
This will set the color of all the elements (except .selected) to red. It will then overwrite that styling and make the succeeding elements blue.
ul li:not(.selected) {
color:red;
}
ul .selected ~ li {
color:blue;
}
Since :not() isn't supported in IE8, you could also use the following:
EXAMPLE HERE
ul li {
color:red;
}
.selected {
color:black;
}
ul .selected ~ li {
color:blue;
}
There is a selector that matches elements preceded by another and this selector is a tilde ~.
So, you can simply match all elements after .selected using:
.selected ~ LI
JSFiddle example.
For futher details, visit spec.

:first-child selector selects more than one children

I'm trying to apply a style to ONLY the very first child of an element. I'm using :first-child in the css to achieve this, but it looks like it's not the behaviour I'm looking for.
Take the following markup as example:
<ul class="myUl">
<ul class="mySubUl">
<li>foo0</li>
<li>foo1</li>
</ul>
<ul class="mySubUl">
<li>foo2</li>
<li>foo3</li>
</ul>
</ul>
======================
<ul class="myUl">
<li>foo0</li>
<li>foo1</li>
<ul class="mySubUl">
<li>foo2</li>
<li>foo3</li>
</ul>
</ul>
and this simple CSS:
ul.myUl li:first-child {
color: red;
}
Live fiddle: http://jsfiddle.net/bsSDh/1/
This applies not only to the first child of the ul.myUl elements, but also to the first child of ul.subUl. I would have expected this behaviour if the CSS selector was ul li:first-child (which works), but since I'm adding a class to the selector I'm expecting to apply that style only to the very first child.
Why does the style applies not only to the first child? Am I missing something about first-child specs or using the selector in the wrong way?
I think you need an additional child selector element like this:
ul.myUl > li:first-child {
color: red;
}
Example Fiddle
Your selector selects any <li> below ul.myUL, that is a first child. As this references only to the immediate parent and not any other ancestor, all those other <li> match as well.
EDIT
After your comment, I assume, that you will need a somehow complexer selector like this:
ul.myUl > li:first-child,
ul.myUl > ul:first-child > li:first-child {
color: red;
}
The selector
ul.myUl li:first-child
selects any li:first-child below any ul.myUl (i.e. first child of any parent inside the ul). Instead you might want to select a direct child via
ul.myUl > li:first-child
or even
ul.myUl > ul.subUl:first-child > li:first-child
Pay attention to the differences between the Child Combinator (a direct child) and the Descendant Combinator (any element contained).
You should use this two selectors to achieve the result wanted on the two known cases:
ul.myUl > ul:first-child > li:first-child {
color: red;
}
ul.myUl > li:first-child {
color: red;
}
Running Demo

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