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/
Related
I'm trying to change the text color of "Sale" item, but not a phone number with only CSS. I can't edit HTML code.
.menu.left a:first-child {
background: yellow;
color: red;
}
Results in both yellow & red
.menu.left li:nth-child(2)`
background: yellow;
color: red;
}
Results in only yellow background
Do you have an idea how to solve this?
You can target the <li> or the <a>
in this case i target the second li and then the a so the font changes to red.
If you only target the li, the font wont change to red.
Hope this is what you were looking for. Happy to explain or help in a better solution if needed.
Example targeting the <a>
.menu.left li:nth-child(2) a{
background-color: yellow;
color: red;
}
<ul class="menu left">
<li>
1231233123
</li>
<li>
Sale
</li>
</ul>
Example only targeting the <li>
.menu.left li:nth-child(2){
background-color: yellow;
color: red;
}
<ul class="menu left">
<li>
1231233123
</li>
<li>
Sale
</li>
</ul>
Comment by OP
"Thank you, Gerardo, your solution worked very well. I run into trouble though with mobile version of this link. Maybe you could take a look? codepen.io/anon/pen/xYJKRW "
On your comment you added a codepen, where you have the same mistake. You are trying to target the <li> when you have to target the <a> try this:
[data-mobile-dropdown-rel="sale"] a {
color: red;
}
.menu.left li:nth-child(2) a {
background: yellow;
color: red;
}
Add color:red; to .menu.left li:nth-child(2) and keep the background:yellow; where it is now. Your trying to change the font color of the <a> tag not the <li>.
This is supposed to work:
ul.menu li:nth-child(2) a {
background-color: yellow;
color: red;
}
For changing color of <a> you have to change color of <a> directly. Otherwise it won't work. In this case you have to change color of <a> not <li>. That is why it does not work.
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;
}
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>
I have a list of items which I am trying to add dividers to right of each using the :before psuedo element.
Unfortunately, it seems like when I use it in combination with both last-child and first-child, it targets every element in the list.
Example - http://codepen.io/anon/pen/rupqi
Markup
<ul class="nav nav--inline nav--secondary">
<li><a class="nav--secondary__item" href="#">Site Map</a> </li>
<li><a class="nav--secondary__item" href="#" title="Search Terms">Search Terms</a> </li>
<li><a class="nav--secondary__item" href="#" title="Advanced Search">Advanced Search</a> </li>
<li><a class="nav--secondary__item" href="#" title="Contact Us">Contact Us</a> </li>
</ul>
CSS
.nav--inline, .nav--inline > li, .nav--inline > li > a { float: left; }
.nav--secondary__item {
color: #706782;
font-size: 1.2em;
padding: 0.8em;
position: relative;
#include transition (background-color 0.5s ease-in-out);
}
.nav--secondary__item:before {
content: "|";
color: #939EB7;
position: absolute;
left: 0;
}
.nav--secondary__item:first-child:before, .nav--secondary__item:last-child:before { content: "*"; }
Does anyone know why this happens, and if so, how to fix it?
Change your css to :
li:first-child .nav--secondary__item:before,
li:last-child .nav--secondary__item:before {
content:"*";
}
Because .nav--secondary__item is first-child as well as last-child of its parent li, following selector applies the content to all of them.
.nav--secondary__item:first-child:before,
.nav--secondary__item:last-child:before
{ content: "*"; }
Fiddle
:first-child pseudoclass selects the first child of its parent, similarly :last-child.
The :first-child CSS pseudo-class represents any element that is the first child element of its parent.
See doc
This is happening because you have a elements inside li elements and you are applying first-child to those a elements.
So .nav--secondary__item:first-child applies to every .nav--secondary__item, because the parents for each a are the surrounding li, not your ul.
Going by your class naming scheme, you can change your HTML to look like this:
<li class="nav--secondary__item">
<a class="nav--secondary__item__link" href="#" title="Site Map">Site Map</a>
</li>
And your CSS for the first-child/last-child will need a slight tweak:
.nav--secondary__item:first-child .nav--secondary__item__link:before,
.nav--secondary__item:last-child .nav--secondary__item__link:before {
content: "*";
}
You will also have to make the styles that apply to the a element use the .nav--secondary__item__link class instead.
Example forked from yours: http://codepen.io/anon/pen/rknmL
To my knowledge, the answer to this is no, can't be done, but I need a second opinion:
If I have the following:
<li>
<a >#</a>
<div class="sub">
#
</div>
</li>
and have a background image that appears on li a:hover is it possible to have that background stay on when hovering on the .sub div? This also has to work pure CSS - no javascript cheats.
My understanding is because .sub isn't a child of the a we can't reference it in css to keep the hover.
Because the image is for only one section of the code, I can't move it to the li and reference li:hover a.
Not sure what all you are trying to achieve, but there are many hover effects that can be done.
SECOND UPDATE: If you don't need to interact (other a tags, etc) at all with anything in the div, then this way cheats to get the effect. Note how the anchor inside the div does not register because of the z-index.
UPDATE I think I understand your issue better now. Can you add a wrapper and do the following?:
Example HTML:
<ul>
<li>
<div>
<a>Some anchor text</a>
<div class="sub">Some div content <a>and anchor</a></div>
</div>
</li>
</ul>
Example CSS:
li:hover {
background-color: cyan;
}
li > div:hover > a {
background-color: green;
}
a:hover {
color: yellow;
display: block;
}
a:hover + .sub {
outline: 1px solid blue;
}
.sub:hover {
color: red;
outline: 1px solid red;
}
If you can't use a class on the li or modify the div.sub to be in the a, you're probably out of luck without Javascript:
Is there a CSS parent selector?
However, if you can, you could use:
<ul>
<li class="sub">
<a>Class #</a>
<div class="sub">#</div>
</li>
<li>
<a>Inner #
<div class="sub">#</div>
</a>
</li>
<li>
<a>None #</a>
<div class="sub">#</div>
</li>
</ul>
li.sub:hover,
li a:hover {
background: url(http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=32&d=identicon&r=PG);
}
li a {
border: 1px solid blue;
display: block;
}
.sub {
border: 1px solid green;
}
http://jsfiddle.net/B7Au2/4/
I don't know if you can modify the html, but if you can, try swapping the div and the a:
<li>
<div class="sub">
#
</div>
<a >#</a>
</li>
Now you can use the adjacent sibling selector:
li a:hover, li .sub:hover + a {background:url('some-image.png')}
Unfortunately there's no way to select the previous element through CSS: that's why you need to swap your elements.