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

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

Related

Css :not pseudo class is not taking effect

I want to use the :not pseudo class as an exception where the css should apply to everything except any element with a certain class including all its children elements.
But in my example, the :not selector is affecting everything, but only should affect the class inside the :not selector. I'm using chrome browser.
fiddle
SCSS:
.ql-editor :not(.not-ql-editor){
ul > li {
background:blue;
}
}
HTML:
<div class="ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
I would have expected the top <ul><li> to have blue background, while the lower <ul><li> would not have a background because it has the .not-ql-editor class, but something seems wrong since no li elements get the background.
Update:
After the answer by Johannes I learned that the upper ul needs to be wrapped inside some element because the :not(.not-ql-editor) represents an element even if it doesn't match the selector.
But then I noticed that the "not-ql-editor" element has to be directly underneath the "ql-editor" element. My aim was to target a class at any level beneath "ql-editor".
Normally when you but a space between two selectors, the second selector should target elements at any level beneath the first one. Is this not the case with the :not selector?
update2:
Here is a modified version of the fiddle:
fiddle2
If the html looks like this (with the same css):
<div class="ql-editor">
<div>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
</div>
The li's become blue. Despite the css: .ql-editor :not(.not-ql-editor)
The problem in your code is that the first list is on a different "descendant level" than the second list: Your CSS selector is valid only for li elements inside a ul which is child of an element that does not have the .not-ql-editor which again is child of an element that has the .ql-editor class.
For this to work you need another div (or other) wrapper around your first ul:
.ql-editor :not(.not-ql-editor) ul>li {
background: blue;
}
<div class="ql-editor">
<div>
<ul>
<li>hello></li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
ADDITION after comments and edit of question:
In the first code example you posted, your ul elements were on different descendant levels from the .ql-editor DIV element: The first ul was a directchild, the second one a grandchild, with the .not-ql-editor DIV as a wrapper between .ql-editor and the ul. My answer was directed at this situation, and it worked.
In the second code example you posted, you added another level: A DIV without any class in between the .ql-editor DIV and the .not-ql-editor DIV. This changes things. In the fiddle you added, the .not-ql-editor DIV is the direct parent of the ul. So you need to use that relationship to define a CSS rule that only applies if the ul is a direct child of a DIV that does not have the .not-ql-editor class.
in plain CSS that rule would be as follows:
.ql-editor *:not(.not-ql-editor) > ul > li {
background: blue;
}
Here's your second code example combined with that CSS rule in a snippet, The background does * not* become blue:
.ql-editor *:not(.not-ql-editor) > ul > li {
background: blue;
}
<div class="ql-editor">
<div>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
</div>
And here's your second fiddle with this CSS applied as SCSS: https://jsfiddle.net/e7d0h4yc/
You can do this with the original HTML you had. Since the top ul element and the div.not-ql-editor element are siblings, you can just attach the not rule to a wildcard element, and instead of targeting ul > li just target li
.ql-editor>*:not(.not-ql-editor) li {
background: blue;
}
<div class="ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
<div class="not-ql-editor">
<ul>
<li>hello</li>
<li>hello</li>
<li>hello</li>
</ul>
</div>
</div>
.ql-editor :not(.not-ql-editor){
ul > li {
background:blue;
}
}
Correct this to remove the space between ql-editor and :not
.ql-editor div :not(.not-ql-editor){
background:blue;
}

Prevent CSS inheritance to children of the selected element

I have a menu consisting of nested ULs and LIs, eg:
.wrapper > ul:first-child > li:last-child {
color: red;
}
<div class="wrapper">
<ul>
<li>Lorem</li>
<li>Ipsum</li>
<li>Dolar</li>
<li>Style me!
<ul>
<li>Lorem</li>
<li>Don't style me!</li>
</ul>
</li>
</ul>
</div>
I want to add a style to the last <li> of the first <ul>, but not have it's children (the nested <ul>) inherit it.
I have tried:
.wrapper > ul:first-child > li:last-child {/*styles*/}
but this still styles the last element.
Would anyone know how I can target just that 1 element (with just CSS)?
Some CSS properties are inherited and you can't prevent that.
Inheritance propagates property values from parent elements to their children.
Some properties are inherited properties, as defined in their
property definition table. This means that, unless the cascade results
in a value, the value will be determined by inheritance.
However, you can override that by selecting the children and restoring the desired value.
.wrapper > ul:first-child > li:last-child {
color: red;
}
.wrapper > ul:first-child > li:last-child > * {
color: initial;
}
<div class="wrapper">
<ul>
<li>Lorem</li>
<li>Ipsum</li>
<li>Dolar</li>
<li>Style me!
<ul>
<li>Lorem</li>
<li>Don't style me!</li>
</ul>
</li>
</ul>
</div>

CSS Class naming convention .sa-list li a > div{..}

I am going through a CSS example, and it has code like this:
.sa-list li label > span,
.sa-list li h3 > span,
.sa-list li h4 > span,
.sa-list li a > div{
position:relative;
display:table-cell;
vertical-align:middle;
padding:10px 20px;
}
Can someone explain what's the relationship between say li, a and div and which style goes where?
These rules all style a span that is direct child of a label, h3 and h4 and a div that is a direct child of an a tag, all of which are a descendant of an li that is also a descendant of an elements with the class of sa-list.
For instance:
<ul class="sa-list">
<li>
<label>
<span><!-- this span is styled --></span>
</label>
</li>
</ul>
<div class="sa-list">
<ul>
<li>
<div>
<h4>
<span><!-- this span is also styled --></span>
</h4>
</div>
</li>
</ul>
</div>
<ul class="sa-list">
<li>
<a>
<div><!-- this div is styled --></div>
<div><!-- as is this div --></div>
<section>
<div><!-- this div is not, b/c it is not a direct child of the a --></div>
</section>
</a>
</li>
</ul>

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