Why does > selector also choose a nested span? [duplicate] - html

This question already has answers here:
Why is a second-child affected by my first-child color property?
(4 answers)
Closed 3 years ago.
Something obvious I may be missing, but I can't figure out why the > selector (which should only select direct children), also styles the nested span #2.
I do get the expected result (only outer span #1 green, span #2 is black) when I add this to the CSS:
span{
color:black;
}
However, I feel it's odd that using just the > selector somehow expands into the nested span, behaving as a space selector targeting all children:
div span{
color:green;
}
Any ideas? (Here's a Codepen I used to fiddle with it)

In short, Inheritance. The style isn't applying directly to the second span. Rather, the second span is "inheriting" its style from the first span.
Look in something like Chrome Dev tools and you'll see this;
Your options here are limited. You could unset any nested spans by resetting them to their initial state;
body{
color: red;
}
div > span{
color: green;
}
div > span > span{
color: initial;
}
<div>
<span>
This is span #1
<span>This is span #2</span>
</span>
</div>
However, this comes with a caveat. This means it won't inherit from anything. Note how it doesn't inherit the red color from the body.

Related

:last-child OR :first-child NOT WORKING if followed by any element [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
first-child not working
(3 answers)
Why doesn't this CSS :first-child selector work?
(1 answer)
Closed last year.
I dont know why the selector :first-child working for 'p' element and NOT :last-child and the same happening for the following span element where :last-child works but not the :first-child. (I suppose that the default parent for all of them is the body element). I found that if I place any element following paragraph element it (p:last-child) doesn't work, even acts weirdly for the following elements(span), why is it not working when I m specifically telling it to select last/first child of the 'p' (or span) element of the parent (in this case the body)?
<html>
<head>
<style>
p:first-child {
background: red;
}
span:last-child {
background: red;
}
</style>
</head>
<body>
<p>The first paragraph.</p>
<p>The second paragraph.</p>
<p>The second paragraph.</p>
<span>A..</span><span>B.. </span><span>C.. </span>
</body>
</html>
EDIT: I just found dat the SPEC for all these :first-of-type, last-of-type, first-child and :last-child says- "the selected element had to have a parent. Beginning with Selectors Level 4, this is no longer required",
Which means there's a glitch in their spec. if they DONT need any parent, then it must work, even if they needed, they have one in my case (the body element). Firstly, as per SPEC, they don't need to be a child anymore, secondly, they are indeed children of the default body element. Hence, all these should work (relative to the parent body).
Because third p is not the last child, and first span is not first child of the parent.
Third p is p:last-of-type, but not p:last-child.
As well, first span is span:first-of-type, but not span:first-child.
p:first-child {
color: red;
}
p:last-child {
color: blue; /*This doesn't work*/
}
p:last-of-type {
color: green;
}
span:first-child {
color: red; /*This doesn't work*/
}
span:first-of-type {
color: blue;
}
span:last-child {
color: green;
}
<div>
<p>The first paragraph.</p>
<p>The second paragraph.</p>
<p>The second paragraph.</p>
<span>A..</span>
<span>B.. </span>
<span>C.. </span>
</div>
You fail to understand how those selectors are meant to work, and do work.
:first-child and :last-child are conditions which must match on their own. Preceding it with a selector like p or span just further constrains the list of elements already matched by :first-child and :last-child.
So p:first-child actually means Find all elements which are the first child elements of their parent; then from those found, give me only the p elements.

Why is the <p> element green? [duplicate]

This question already has answers here:
CSS :not pseudo-class applying broadly and not targeting specific element
(4 answers)
Closed 4 years ago.
I was looking at this CSS example from the Mozilla page for the :not() selector.
The example is:
p:not(.classy) { color: red; }
:not(p) { color: green; }
<p>Irgendein Text.</p>
<p class="classy">Irgendein anderer Text.</p>
<span>Noch mehr Text<span>
What I totally understand:
I get why the first p element is red, it's because it is a p element and it does not have the class 'classy'.
I also get why the span element is green, it's because it's selected by the :not(p), it is not a p element
But why is the second p element green? It would not be selected by the first selector, because it is a p element without the class classy. But it would not be selected by the second one, because it is a p element. So why is it green?
The second p isn't :not(.classy) so it isn't color: red. This means it still has its default colour, which is color: inherit.
The body element is :not(p) so it is color: green.
The second p therefore inherits the green colour from the body element.
The developer tools in your browser would have told you this:
In Addition to #Quentin answer, for your understand try to add your elements under one parent and apply the CSS with parent selector reference. Now you will get exactly what you expected. Look at the below snippet.
.test p:not(.classy) { color: red; }
.test :not(p) { color: green; }
<div class="test">
<p>Irgendein Text.</p>
<p class="classy">Irgendein anderer Text.</p>
<span>Noch mehr Text</span>
</div>
So in your case the parent element is body and inherited the color from there like the above answer.

How to target direct text and not text within tags?

Is there a way to only target the direct text within a <h1>-Tag?
Here is an example on what I want to do:
<h1>I want to select this text with a css selector <small>but not this text</small></h1>
This does not seem to work:
h1:not(small)
Is it even possible?
h1:not(small)
Your selector h1:not(small) doesn't work because it says this:
Target all h1 elements that are not small elements.
It's that same as using the h1 selector by itself.
h1 :not(small)
You would have been closer with h1 :not(small), which says:
Target all descendants of an h1 except small elements.
Boom! Exactly what you want.
Except that text contained directly inside an element (i.e, text with no tags around it) becomes an anonymous element. And anonymous elements are not selectable by CSS.
h1 :not(small) {
color: orange;
}
<h1>This text is contained directly inside the container. It is not selectable by CSS. It is an anonymous element. <small>This text is inside a small element</small></h1>
<hr>
<h1><span>This text is contained in a span. It is selectable by CSS</span> <small>This text is inside a small element</small></h1>
CSS Parent Selector
For the small element to be excluded it would have to identify itself as a child of the h1.
But there is no parent selector in CSS.
Solution: Two selectors
You need two selectors to make this work:
The first sets the style on the parent.
The second overrides the first on the child.
h1 {
color: orange;
}
h1 > small {
color: black;
}
<h1>I want to select this text with a css selector <small>but not this text</small></h1>
More Information
Targeting text nodes with CSS
Is it possible to style anonymous flex items explicitly?
Is it possible to select elements not preceded by text?
This is the closest it gets to retaining the style without any css that has been implemented by the parent div. This feature hasn't been fully integrated in all browsers, but it should work for some. Hope, it helps.
Browser support -
What's being done here?
The small tag is retaining its original CSS without being affected by the other styles. You can apply this on any of the child elements whose style you want to preserve.
small {
all: initial;
* {
all: unset;
}
}
h1 {
color: #ff0000;
}
<h1>I want to select this tex with a css selector <small>but not this text</small></h1>
Apply styles to h1 however you want, then, revert those changes in small, for example, if you only want to change the color you would use this code;
h1 { color: red; }
h1 small { color: initial; }
Or, if you have multiple style changes;
h1 {
color: red;
font-weight: italic;
text-transform: uppercase;
}
h1 small {
color: initial;
font-weight: initial;
text-transform: initial;
}
Please note that the initial CSS value can be used on every browser, except for IE and Opera Mini. View this page for more information

Doesn't CSS first-child or last-child work with class wise? [duplicate]

This question already has answers here:
CSS selector for first element with class
(23 answers)
Closed 6 years ago.
Maybe this question is ridiculous, but I want to know this fact. I have a li element with two classes (see below), but it is not working as I expected. Does anybody know the reason?
.red:first-child {
color:#F00;
}
.blue:first-child {
color:#00F; /* not working */
}
.red:last-child {
color:#F00; /* not working */
}
.blue:last-child {
color:#00F;
}
<ul>
<li class="red">one</li> <!-- This is the first child of red -->
<li class="red">two</li>
<li class="red">three</li>
<li class="blue">one</li> <!-- and this first child of blue -->
<li class="blue">two</li>
<li class="blue">three</li>
</ul>
As others have mentioned, :first-child is working as expected, as the first child of the parent.
The :first-child selector is used to select the specified selector, only if it is the first child of its parent.
Source: CSS :first-child Selector
You can reach the first .blue like this:
.red + .blue
or if you want to get all the .blue after .red
.red ~ .blue
You might want to use :first-of-type which selects the first of a type but then those .blue would have to be a different HTML element.
div.red:first-of-type {
color:#F00;
}
div.red:last-of-type {
color:#00F;
}
p.blue:first-of-type {
color:#F00;
}
p.blue:last-of-type {
color:#00F;
}
<div>
<div class="red">one</div>
<div class="red">two</div>
<div class="red">three</div>
<p class="blue">one</p>
<p class="blue">two</p>
<p class="blue">three</p>
</div>
Because It consider Li list. First you have to mention first-childs so take first command to show red. THen Take last code as blue last-child so take last code to show blue.
It not consider the red and blue class orders. It consider li list and periorities.
It doesn't work because what you said to the browser was (for the red case, the blue one is similar):
Locate all elements .red.
From that list of .red elements, pick the first one (first-child).
Apply the red color to it.
The browser works as expected and apply the red color to the first element of the list.
EDIT:
The blue case is due to the fact that CSS always looks for the most precise rule. If both rules has the same precision level, the last one wins, so in this case, the last .blue:last-child wins and the .blue:first-child is ignored.

CSS only get text [duplicate]

This question already has answers here:
Is there a CSS selector for elements containing certain text?
(20 answers)
Closed 8 years ago.
I'm trying to find some text inside an element using a css selector, but not include the children of the element. For example:
<div id="information">
This is the text I need
<div>I don't want this text</div>
<span>I also don't want this</span>
</div>
Any ideas?
NOTE: I'm parsing a page so I don't have control over the elements
Apparently not possible using CSS Selectors. With XPath though, if someone is interested:
//div[#id='information']/text()
So you want the loose text inside of #information but you don't want the div and the span? Seems quite simple:
#information {
/* property values */
}
#information > div {
display: none; /* removes content of child div */
}
#information > span {
display: none; /* removes content of child span */
}
I guess you don't really even have to use the child (>) selector, too.
There is no CSS selector to select just the text content of an element. There is nothing illogical about the idea (CSS could have a pseudo-element for the purpose), but currently there is no specification or even draft on such matters.
What you can do is to set styles on an element and then override them on any child element, possibly using a selector like #information * that matches all descendant elements or #information > * that matches all child elements.