How to use :not and :first-child pseudo selectors simultaneously - css

I want to select the first li without class="test" using :not and :first-child pseudoclasses. In this example I try to set color blue to <li>Third</li>:
ul li {
color:red;
}
ul li:not(.test):first-child {
color:blue;
}
<ul>
<li class="test">First</li>
<li class="test">Second</li>
<li>Third</li>
<li>Fourth</li>
</ul>

Why not do the below, which uses a combination of rules to filter the item you need (you can combine rules #1 and #3).
This has the added advantage of it not mattering what the index is of the first item with the class .test
ul li { /* <-- select all list items */
color: red;
}
li:not(.test) { /* <-- select all list which arent test */
color: blue;
}
ul li:not(.test) ~ li { /* <-- select all list items which follow an item without test */
color: red;
}
<ul>
<li class="test">First</li>
<li class="test">Second</li>
<li>Third</li>
<li>Fourth</li>
</ul>

Related

CSS :not Function Not Working [duplicate]

This question already has answers here:
Remove underline only from anchor element child
(7 answers)
Closed 5 years ago.
I have a problem with css :not function.
When I hovering to link there is underline both of them Item1 & Description. I don't want to see underline below Description when hover.
Here is my menu code:
<ul>
<li>
<a href="#">
Item 1
<span>Description</span>
</a>
</li>
</ul>
CSS:
span { display:block; }
ul li a:hover:not(span) { color:blue; text-decoration: underline; }
When I change span display to inline-block it is working nice but need to be only block. How can I solve it ?
Also, Inline-block shows the description NEAR of the Item. I want to put it under of the Item Name. How can I make it ?
you are saying to the style a:not(span), A that is not a SPAN, of course a isn't a span ;)
Use a css class for this purpose for instance like :
span { display:block; }
ul li a:not(.has-span):hover { color:red; text-decoration: underline; }
<ul>
<li>
<a href="#">
Item 1
<span>Description</span>
</a>
</li>
<li>
<a href="#" class="has-span">
Item 2
<span>Description</span>
</a>
</li>
</ul>
You shouldn't put your state (:hover) before the selector. So you need to change it to:
ul li a:not(span):hover { color:blue; text-decoration: underline; }
And moreover this will not work, because, a single element cannot be a <a> as well as a <span>. Instead you need to just use:
span { display:block; }
ul li a:hover { color:blue; text-decoration: underline; }
ul li a:hover span { color:black; text-decoration: none; }

How to target a selector only if it's NOT child of a specific element (so only if it's the root)

I don't understand why the following code has not desired behaviour:
.toggle {
color: red;
}
:not(.list) .toggle {
font-weight:bold;
}
<div class="container">
Toggle
<ul class="list">
<li>Link 1</li>
<li>
<div class="container">
SubToggle
<ul class="list">
<li>SubLink 1</li>
<li>
SubLink 2
</li>
<li>SubLink 3</li>
</ul>
</div>
</li>
<li>Link 3</li>
</ul>
</div>
I thought that using :not() would result in applying "bold" only to main "Toggle" link but instead it applis "bold" to all of red ones. Why?
Please, note that this code is nested with same class names, I don't want to target specific levels with different css classes, I would like to target elements only with descendant selectors and other operators
Here is present also a jsFiddle to directly try.
I think you might want this:
.toggle {
color: red;
font-weight: bold;
}
div *:not(.list) .toggle {
font-weight: normal;
}
:not does not support CSS Combinators.
Your only way to do this is:
.toggle {
color: red;
}
.toggle {
font-weight:bold;
}
.list .toggle {
/* Override previous */
}
Fiddle
I tried so many times but this is the only way I can do:
.toggle {
color: red;
font-weight:bold;
}
.list .toggle{
//override
font-weight:normal;
}
This is how to use :not the right way:
add specialToggle for elements you do not want to select
SubToggle
and then css:
.toggle {
color: red;
}
.toggle:not(.specialToggle) {
font-weight:bold;
}
https://jsfiddle.net/s249tyur/3/
If the structure is always going to be the same you could try using the greater-than sign (>), it means only apply the style to the immediate children of the class.
.container > .toggle {
font-weight:bold;
}
Or if the container is not always going to have the same class, but is always a div element you could use:
div > .toggle {
font-weight:bold;
}

nth-child targets only children

<ul id="main-menu">
<li>111
<ul id="sub-menu">
<li>sub-111</li>
<li>sub-222</li>
<li>sub-333</li>
<li>sub-444</li>
</ul>
</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<style>
ul#main-menu li:nth-child(2n) {
color: red;
}
</style>
this is a demo
http://cssdeck.com/labs/emxvbal4
This effects the sub items also !!
How can I target only the li's of the main-menu without touching the li's of the sub-menu
Use the child combinator (>) instead of the descendant one ():
ul#main-menu > li:nth-child(2n)
Use direct children selector:
#main-menu > li{
}
Use immediate children selector ">".
ul#main-menu > li {
<your_css_style>
}
For more info., check this LINK.

Hide first <li> element

My HTML structure is as per the following:
<nav class="main-nav">
<ul>
<li class="gallery-collection">
Welcome <!-- Hide this -->
</li>
<li class="page-collection">
About
</li>
<li class="gallery-collection">
Support
</li>
...
How do I hide the first element saying "Welcome" using CSS? Note that 2 elements have the same class here: 'gallery-collection'.
Max compatibility:
.main-nav li {
display: none;
}
.main-nav li + li {
display: list-item;
}
Less compatibility, but not too bad:
.main-nav ul li:first-child {
display: none;
}
With CSS only (as your question was only tagged css):
.main-nav li:first-of-type
{
display:none;
}
The :first-of-type selector is supported in all major browsers, except IE8 and earlier.

CSS inheritance broken?

i have nested lists with links inside the li tags. On nesting level x I want to change the appearance of the links. Just some sample code:
CSS:
.blue a { color: blue; }
.red a { color: red; }
HTML:
<ul>
<li class="blue">blue-1</li>
<li class="red">red-1</li>
<li class="blue">blue-2
<ul>
<li>
blue-3
<ul>
<li class="red">
red-2
<ul>
<li>red-3</li>
<li>red-4</li>
</ul>
</li>
<li>blue-4</li>
</ul>
</li>
<li class="">blue-5</li>
</ul>
</li>
<li class="red">red-5
<ul>
<li>red-6</li>
<li>red-7</li>
</ul>
</li>
</ul>
In that way it is working as expected. Links with text red-* are in red. But when I change the order of the CSS classes, it is not longer working:
.red a { color: red; }
.blue a { color: blue; }
Why this behavior? Shouldn't it be the same?
I have to use more colors than red and blue, so it is impossible to give a correct order in CSS.
Css selector precedence is set according to how specific it is:
every tag is counted as 1 point
every class as 10 points
event id as 100 points
Both selectors you got have the same precedence, so that one which is set further in code overrides previous ones.
The reason for this is that in your css you're telling every a tags that are child, grandchild, etc. elements of a class named blue. And that's getting overidden when you're telling that every a tags that are child, grandchild, etc. elements of a class named red should be red.
So instead of doing this (affecting all link tags)
.blue a { color: blue; }
.red a { color: red; }
You could do this (affects only the first child if it's a link tag):
.red > a,
.red > ul > li > a{ color: red; }
.blue > a,
.blue > ul > li > a { color: blue; }
What that second line does is it finds all elements that has a class name red. Then it finds all direct child ul elements. And under those matching elements it finds all direct child li elements that has direct child a elements. Matching these, it finally adds styles.
JSFiddle:
http://jsfiddle.net/Y9jFr/

Resources