What is the difference between separating CSS items with "space" or ">" - css

Say, we have this code:
<div>
<ul>
<li></li>
</ul>
</div>
What is the difference between <style>div ul li { ... }</style> and <style>div > ul > li { ... }</style>?

The space is a descendant selector. It will apply styles to all matching descendants (children, grandchildren, great-grandchildren...)
The > is a child selector. It will only apply to children of the parent.
Let's use this HTML as an example:
<section class=foo>
<div class=blue>
<span class=blue></span>
</div>
</section>
Let's style it with the descendant selector:
.foo .blue {
color: blue;
}
With the above CSS, both the div and the span will be blue. In fact, any element inside .foo will turn blue if you give it the class "blue".
Now look at this CSS:
.foo > .blue {
color: blue;
}
With this CSS, only the div will be blue. The span will not be blue despite having the class "blue", as it is not a child of .foo

Related

How to style parent element based on his child [duplicate]

This question already has answers here:
Is there a CSS parent selector?
(33 answers)
Closed 5 months ago.
Let's say our html structure looks like this:
<div class="parent">
<div class="child"></div>
</div>
Now on some button action I add active className to child's div.
My question is:
How to style only parent element if child's div has active className
// CSS pseudo code //
if(child.has.className('active')
.parent{
background: red;
}
You can use the :has() pseudo class selector, although that's only supported in newer browsers. Otherwise you'll probably need to use JS.
.parent {
background: #ccc;
}
.parent:has(.active) {
background: steelblue;
color: #eee;
}
/* Ignore below, for stylistic purposes only */
.parent {
margin: 1rem;
padding: 1rem;
border-radius: .5rem;
font-family: Arial, sans-serif;
}
<div class="parent">
<div class="child">Child</div>
</div>
<div class="parent">
<div class="child active">Child (active)</div>
</div>
For a JS-based solution there are two ways:
Recommended: in the code that adds the active class, you also toggle a class on the parent, say has-active-child and style it accordingly
Not recommended: listen to class changes on the child node using MutationObserver API and style the parent node
At the moment not all browsers support the pseudo class selector :has() as Terry explained. A JavaScript solution goes as following.
Example from GeeksForGeeks
$('ul li:has(ul.child)').addClass('has_child');
.parent > li > ul > li {
background:orange;
}
.parent > li.has_child {
background:red;
}
.parent li {
background:blue;
color:black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<style>
.parent li {
background:blue;
color:black;
}
.parent > li > ul > li {
background:orange
}
.parent > li > ul > li > ul >li {
background:pink;
}
</style>
</head>
<body>
<ul class="parent">
<li>I am first</li>
<li>I am second</li>
<li>I am third</li>
<li>I am forth</li>
<li>I have kids.
<ul class="child">
<li>child1</li>
<li>child2
<ul>
<li>child2.1</li>
<li>child2.2</li>
<li>child2.3</li>
</ul>
</li>
<li>child3</li>
<li>child4</li>
<li>child5</li>
</ul>
</li>
<li>I am sixth</li>
<li>I am seventh</li>
<li>I am eight</li>
</ul>
</body>
</html>

Confused about inheritance when using the general sibling combinator "~"(tilde)

So nothing happens when I try to color list items in an unordered list using the general sibling combinator:
http://jsfiddle.net/bkbehpv0/
p {
color: blue
}
h1 ~ li {
color: red;
}
<h1> Title of site </h1>
<p> Text in the site </p>
<p> Second paragraphy </p>
<ul>My list
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
But a span inside of a paragraph colors with no problems at all:
http://jsfiddle.net/93khsvbn/
p {
color: blue
}
h1 ~ p span {
color: red;
}
<h1> Title of site </h1>
<p> Text in the site </p>
<p> Second paragraphy <span> heyo </span></p>
<ul>My list
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
Sooo... is the span on equal footing with the paragraph when it comes to inheritance even though it's nested inside of the paragraph? Why?
I can't seem to find a thorough source from which I could learn about inheritance.
Also, just as an aside... how do I style the title of an unordered list without styling the list items? Do I HAVE to assign an identifier to the ul?
If I style the ul the list items will inherit that styling as well.
In your first example (h1 ~ li) you are saying:Find any li which are siblings to and preceded by a h1. As the li belong to a ul this rule is not matched.
The second example (h1 ~ p span) you are saying:Find any spans which are children to p which is a sibling to and preceded by a h1. So the rule is matched.
To get the first rule to match you should instead use h1 ~ ul li. This effectively says:Find any lis which are children to ul which is a sibling to and preceded by a h1.
p {
color: blue
}
h1 ~ ul li {
color: red;
}
<h1> Title of site </h1>
<p>Text in the site</p>
<p>Second paragraphy <span> heyo </span></p>
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
It should also be noted that the text "My List" is not valid in the ul, it should be surrounded by li tags. To differentiate it from the other li you could either:
Add a class: <li class="heading">My List</li>
Move it outside the list: <h2>My List</h2><ul>
Use the first-child selector: li:first-child {color:green;}
p {
color: blue
}
li:first-child {
color:green;
}
h1 ~ ul li {
color: red;
}
<h1> Title of site </h1>
<p>Text in the site</p>
<p>Second paragraphy <span> heyo </span></p>
<ul>
<li>My List</li>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
First of all, as Joshua K said, the <h1> is sibling (meaning in the same dom level) as <ul>. So as said, you can access a sibling's children like this
h1 ~ ul > li
I don't know if there is a complete inheritance guide but you can read about CSS selectors here and consequently learn about the dom inheritance and element relations.
As for your final question, there is no header in a <ul>. In your example "My list" is just plain text. You can style it with two ways.
1) (the bad way) style the whole <ul> and the overide the attributes in the <li> elements.
2) wrap your title around an element e.g. <span>My List</span> and apply style in ul>span

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.

CSS: complex selector :parent and :not

I have this html code:
<div class='ui'>
<h3 class='title'>
<a href='#'>Link to Header</a>
</h3>
</div>
<a href='#'>Another link</a>
I want to set a CSS style for all anchors a, but not the one that are into an h3 element that is parent of div.ui. I cannot add a class to the anchor a into h3 element.
I try this one:
a:not(:parent:parent.ui){color:#dedede;}
but this not work.
Any solution?
As Kobi noted in a comment, there is no such :parent selector.
Instead I suggest you style all a tags, then style a tags within h3 tags within a different rule:
a {
color: #dedede;
}
.ui h3 a {
color: another color;
}

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