CSS selector "*:before" [duplicate] - css

Does the universal selector * affect pseudo elements like :before and :after?
Let me use an example:
When doing this:
* { box-sizing: border-box; }
...doesn't the above declaration automatically include/affect pseudo elements like :before and :after as well?
Or, in order to affect pseudo elements like :before and :after, one has to declare this?
*, *:before, *:after { box-sizing: border-box; }
Does this make sense?
I have always used just * { box-sizing: border-box; } and never have had any issues with pseudo elements whatsoever. But I see many tutorials doing *, *:before, *:after but they never really explain why they include *:before, *:after in the declaration.

No, the universal selector * does not affect pseudo-elements (except indirectly via inheritance, as pseudo-elements are typically generated as children of actual elements).
The universal selector, like other named element selectors such as p and div, is a simple selector:
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
A simple selector, and by extension any complex selector, targets only actual elements.
Although pseudo-elements (which are not the same thing as pseudo-classes mentioned above) can appear in selector notation alongside simple selectors, pseudo-elements are completely separate from simple selectors as they represent abstractions of the DOM that are separate from actual elements, and therefore both represent different things. You cannot match a pseudo-element using a simple selector, nor can you apply styles to an actual element in a CSS rule with a pseudo-element in its selector.
So, in order to match :before and :after pseudo-elements of any element, yes, one will need to include *:before, *:after in the selector. Having just * { box-sizing: border-box; } will not affect them since box-sizing is not normally inherited, and as a result, they will retain the default box-sizing: content-box.
One possible reason why you might never have had any issues with pseudo-elements is that they're displayed inline by default, as box-sizing has no effect on inline elements whatsoever.
Some notes:
As with any other chain of simple selectors, if * is not the only component then you can leave it out, which means *, :before, :after is equivalent to *, *:before, *:after. That being said, the * is usually included for the sake of clarity — most authors are used to leaving the * out when writing ID and class selectors, but not pseudo-classes and pseudo-elements, so the notation may seem strange and even wrong to them (when it is in fact perfectly valid).
The current Selectors specification that I link to above represents pseudo-elements with double colons. This is a new notation introduced in the current spec to distinguish pseudo-elements from pseudo-classes, but most box-sizing resets use the single colon notation to accommodate IE8, which supports box-sizing but not the double colon notation.
Although *:before, *:after applies styles to the respective pseudo-elements of any element, which includes html, head and body, the pseudo-elements will not actually be generated until you apply the content property. You do not have to worry about any performance issues as there are none. For a detailed explanation, see my answer to this related question.

I can only cite from the specification:
The universal selector, written "*", matches the name of any element type. It matches any single element in the document tree.
Element types are for example span and div.
Since pseudo elements don't have an "element type" and are not part of the document tree, it looks like the answer is no, it does not include pseudo elements.
However, since pseudo elements inherit the CSS properties from their "parent" (at least the ones that are inheritable) and the universal selector also affects the parent, it indirectly affects the pseudo elements.
Example
the color is inherited
the border style is not and the ::before element doesn't have a border

Related

CSS before and after selectors with multiple asterisks and commas [duplicate]

Does the universal selector * affect pseudo elements like :before and :after?
Let me use an example:
When doing this:
* { box-sizing: border-box; }
...doesn't the above declaration automatically include/affect pseudo elements like :before and :after as well?
Or, in order to affect pseudo elements like :before and :after, one has to declare this?
*, *:before, *:after { box-sizing: border-box; }
Does this make sense?
I have always used just * { box-sizing: border-box; } and never have had any issues with pseudo elements whatsoever. But I see many tutorials doing *, *:before, *:after but they never really explain why they include *:before, *:after in the declaration.
No, the universal selector * does not affect pseudo-elements (except indirectly via inheritance, as pseudo-elements are typically generated as children of actual elements).
The universal selector, like other named element selectors such as p and div, is a simple selector:
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
A simple selector, and by extension any complex selector, targets only actual elements.
Although pseudo-elements (which are not the same thing as pseudo-classes mentioned above) can appear in selector notation alongside simple selectors, pseudo-elements are completely separate from simple selectors as they represent abstractions of the DOM that are separate from actual elements, and therefore both represent different things. You cannot match a pseudo-element using a simple selector, nor can you apply styles to an actual element in a CSS rule with a pseudo-element in its selector.
So, in order to match :before and :after pseudo-elements of any element, yes, one will need to include *:before, *:after in the selector. Having just * { box-sizing: border-box; } will not affect them since box-sizing is not normally inherited, and as a result, they will retain the default box-sizing: content-box.
One possible reason why you might never have had any issues with pseudo-elements is that they're displayed inline by default, as box-sizing has no effect on inline elements whatsoever.
Some notes:
As with any other chain of simple selectors, if * is not the only component then you can leave it out, which means *, :before, :after is equivalent to *, *:before, *:after. That being said, the * is usually included for the sake of clarity — most authors are used to leaving the * out when writing ID and class selectors, but not pseudo-classes and pseudo-elements, so the notation may seem strange and even wrong to them (when it is in fact perfectly valid).
The current Selectors specification that I link to above represents pseudo-elements with double colons. This is a new notation introduced in the current spec to distinguish pseudo-elements from pseudo-classes, but most box-sizing resets use the single colon notation to accommodate IE8, which supports box-sizing but not the double colon notation.
Although *:before, *:after applies styles to the respective pseudo-elements of any element, which includes html, head and body, the pseudo-elements will not actually be generated until you apply the content property. You do not have to worry about any performance issues as there are none. For a detailed explanation, see my answer to this related question.
I can only cite from the specification:
The universal selector, written "*", matches the name of any element type. It matches any single element in the document tree.
Element types are for example span and div.
Since pseudo elements don't have an "element type" and are not part of the document tree, it looks like the answer is no, it does not include pseudo elements.
However, since pseudo elements inherit the CSS properties from their "parent" (at least the ones that are inheritable) and the universal selector also affects the parent, it indirectly affects the pseudo elements.
Example
the color is inherited
the border style is not and the ::before element doesn't have a border

Strange use of CSS ::before, ::after

Saw this bit of CSS in a Sitepoint example (from this article), and can't understand what it's supposed to do. Obviously the first selector applies the box-sizing style to everything, but I don't understand the use of ::before/::after in this case. I know those are used to add content before or after a given element, but what purpose does it serve here?
*,
*::before,
*::after {
box-sizing: border-box;
}
This will force any ::before or ::after element to use the box-sizing property as well, as you can shape them as if they are boxes. The * does not include these pseudo-elements, so *::pseudo will do that for you.
thats the old implementation of :
The double colon replaced the single-colon selectors for
pseudo-elements in CSS3 to make an explicit distinction between
pseudo-classes and pseudo-elements. For backward compatibility, the
single-colon syntax is acceptable for pre-CSS3 selectors. So, :after
is a pseudo-class and ::after is a pseudo-element
the : is used for :before and :after pseudo-elements which together with the content: allow you to put something for example an image or icon etc before/after every selector you specified
So, here you are selecting everything and applying box-sizing property and style before and after it, as * does not include psuedo-elements
The selector means:
apply to all elements, apply to contents before each element, and apply to contents after each element.

Universal selector * and pseudo elements

Does the universal selector * affect pseudo elements like :before and :after?
Let me use an example:
When doing this:
* { box-sizing: border-box; }
...doesn't the above declaration automatically include/affect pseudo elements like :before and :after as well?
Or, in order to affect pseudo elements like :before and :after, one has to declare this?
*, *:before, *:after { box-sizing: border-box; }
Does this make sense?
I have always used just * { box-sizing: border-box; } and never have had any issues with pseudo elements whatsoever. But I see many tutorials doing *, *:before, *:after but they never really explain why they include *:before, *:after in the declaration.
No, the universal selector * does not affect pseudo-elements (except indirectly via inheritance, as pseudo-elements are typically generated as children of actual elements).
The universal selector, like other named element selectors such as p and div, is a simple selector:
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
A simple selector, and by extension any complex selector, targets only actual elements.
Although pseudo-elements (which are not the same thing as pseudo-classes mentioned above) can appear in selector notation alongside simple selectors, pseudo-elements are completely separate from simple selectors as they represent abstractions of the DOM that are separate from actual elements, and therefore both represent different things. You cannot match a pseudo-element using a simple selector, nor can you apply styles to an actual element in a CSS rule with a pseudo-element in its selector.
So, in order to match :before and :after pseudo-elements of any element, yes, one will need to include *:before, *:after in the selector. Having just * { box-sizing: border-box; } will not affect them since box-sizing is not normally inherited, and as a result, they will retain the default box-sizing: content-box.
One possible reason why you might never have had any issues with pseudo-elements is that they're displayed inline by default, as box-sizing has no effect on inline elements whatsoever.
Some notes:
As with any other chain of simple selectors, if * is not the only component then you can leave it out, which means *, :before, :after is equivalent to *, *:before, *:after. That being said, the * is usually included for the sake of clarity — most authors are used to leaving the * out when writing ID and class selectors, but not pseudo-classes and pseudo-elements, so the notation may seem strange and even wrong to them (when it is in fact perfectly valid).
The current Selectors specification that I link to above represents pseudo-elements with double colons. This is a new notation introduced in the current spec to distinguish pseudo-elements from pseudo-classes, but most box-sizing resets use the single colon notation to accommodate IE8, which supports box-sizing but not the double colon notation.
Although *:before, *:after applies styles to the respective pseudo-elements of any element, which includes html, head and body, the pseudo-elements will not actually be generated until you apply the content property. You do not have to worry about any performance issues as there are none. For a detailed explanation, see my answer to this related question.
I can only cite from the specification:
The universal selector, written "*", matches the name of any element type. It matches any single element in the document tree.
Element types are for example span and div.
Since pseudo elements don't have an "element type" and are not part of the document tree, it looks like the answer is no, it does not include pseudo elements.
However, since pseudo elements inherit the CSS properties from their "parent" (at least the ones that are inheritable) and the universal selector also affects the parent, it indirectly affects the pseudo elements.
Example
the color is inherited
the border style is not and the ::before element doesn't have a border

How does the browser render pseudo element selectors?

What I'm particularly wondering is how expensive *:after would be, resource-wise.
Would the pseudo element become the key selector in this case? Or would the client grab all the elements anyway?
In other words, what's the difference between the *:after and * performance-wise?
[edited. stupid example. my bad.]
For clarification, I'm trying my hand at drawing sth using only css and found myself using a lot of pseudo elements. Just wandering if I can save myself some time by writing
*:after,
*:before {
content:'';
}
and its resource cost.
Thanks.
Would the pseudo element become the key selector in this case?
Technically, the subject of the selector is *, meaning whichever element is matched by * will be the one generating the pseudo-element.
The term "key selector" isn't well-defined when it comes to pseudo-elements, plus unlike the concept of subject selectors it's actually an implementation detail. If "key selector" means "selector representing the box that is rendered", then I suppose you could say that the pseudo-element is the key selector. I'm not familiar with implementation details, though, since I'm not an implementer.
Either way, it's safe to assume that the client walks through the DOM and, for every element that it picks out:
Attempt to match the element against the selector, ignoring the pseudo-element for now (in this case, *).
If the element matches the selector, attempt to create a pseudo-element box as a child of this element's box (in the case of generated pseudo-elements like :before and :after) if it is applicable (some elements cannot generate pseudo-elements).
Apply styles to the pseudo-element box and render it as with any other box.
The difference between your two selectors is that the former contains a pseudo-element while the latter does not. Since they do fundamentally different things, it's not fair to compare them by performance. However, they both do attempt to match any element in the DOM as they both use the same catch-all selector *, so barring any special optimizations, it's safe to assume that the only overhead that comes with *:after lies with actually generating and rendering the pseudo-element.
Since we're on the topic of performance, remember that matching an element to * is almost instantaneous as it's basically a guaranteed match; it's only when you combine it with more complex selectors that it gets more expensive on a selector level, and while ultimately its performance scales the greatest with the number of elements you have in the DOM, it's still not nearly as expensive as actually rendering the styles unless you have elements in the thousands.
As for your use case, my opinion is that you generally do not need to create pseudo-elements for every element. If you're drawing something with CSS, see if you can limit your selector by context so you avoid rendering unnecessary boxes across the entire DOM, e.g. if you're only drawing within an element with a certain ID:
#mycanvas *:after,
#mycanvas *:before {
content:'';
}
After Question Edited
Just got a clear picture of what you are trying to ask here, so when you use *, it is going to select the elements anyways but that won't be precise as it selects all elements.. If you want, you can use something like
.container *:not(span) {
color: red;
}
Or (But the below one will select all elements nested inside .container)
.container * {
color: red;
}
Demo
Before Question Edited
I am not able to understand what are you asking here, but both selectors are COMPLETELY DIFFERENT.. they are used for different purposes, I don't know whether it's a typo in your question, but using *:after is often used with content which has to be embedded :before or :after.
So, for example
*:after {
content: " <";
}
Demo
And when you use this, * .after, will select elements having class .after
* .after {
color: red;
}
Demo 2
As far as the optimization goes, I don't think using * in general websites is a huge performance issue, I often use the selector below holding properties like
* {
margin: 0;
padding: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
Also, last but not the least, I don't find any reason to use *:after as you won't be embedding some content using :after for each element.

Can I target a :before or :after pseudo-element with a sibling combinator?

Is there a reason why this CSS doesn't work?
http://jsfiddle.net/6v5BZ/
a[href^="http"]:after {
content:"";
width:10px;
height:10px;
display:inline-block;
background-color:red;
}
a[href^="http"] img ~ :after {
display:none;
}
.. on this HTML?
Test
<a href="http://google.com">
<img src="https://www.google.com/logos/classicplus.png">
</a>
The idea is to have a pseudo-element on matching anchor tags. But I do not want it to apply to anchor tags that wrap an image. And since I can't target anchors using something like a < img, I figured the maybe I could target the :after pseudo-element by finding an image that it's a sibling of.
Any insight would be greatly appreciated.
You can't target :after since it's content is not rendered in the DOM and it does not manipulate it - for this to work the DOM would have to be re-rendered and CSS can't manipulate it like this.
Check the specification for detailed understanding: http://www.w3.org/TR/CSS2/generate.html#propdef-content
Generated content does not alter the document tree. In particular, it
is not fed back to the document language processor (e.g., for
reparsing).
I suggest you use JavaScript to do the job for you.
You cannot use a combinator to target a pseudo-element relative to elements other than its generating element.
This is because they're pseudo-elements, not actual elements, and combinators only work by establishing relationships between actual elements. A pseudo-element, on the other hand, can only be applied to the subject of a selector (the rightmost compound selector), and this happens only after matching is processed on the real elements. In other words, matching is done first as though the pseudo-element wasn't there, then the pseudo-element, if it's indicated within the selector, is applied to each match.
In your code, the following selector:
a[href^="http"] img ~ :after
Does not actually look for an :after pseudo-element that comes after an img within the a, even though it appears that way as both are rendered as children of the a element.
It can be rewritten into the following:
a[href^="http"] img ~ *:after
Notice the * selector, which is implied. Similarly to how you can omit * before any other simple selectors for it to be implied, omitting * from a pseudo-element also makes it implied to be there. See the spec for details.
Now, even though it appears *:after should still match a:after (since a would match *), it still doesn't work that way. If you remove the :after pseudo-element from the selector:
a[href^="http"] img ~ *
You'll notice that the meaning of the selector changes entirely:
Select any element
that appears as a following sibling of an img
that is a descendant of an a (whose href starts with "http").
Since the img is the last child of the a element in your HTML, there are no following siblings to match, and therefore no :after pseudo-elements can be generated.
In the case of a :before or :after pseudo-element, one might think of matching the pseudo-element's generating element relative to the pseudo-element's "sibling", but as the OP has correctly pointed out, there is no parent selector, so they're out of luck there, too.

Resources