Strange use of CSS ::before, ::after - css

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.

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

What is the difference between pseudo-classes and pseudo-elements?

What is the difference between div::after {} and div:after {} ? When do we have to use :: over :?
Double colon and single-colon notation is to distinguish between
pseudo-classes and pseudo-elements.
What is the actual meaning of the above statement?
From https://developer.mozilla.org/en-US/docs/Learn/CSS/Introduction_to_CSS/Pseudo-classes_and_pseudo-elements
Pseudo-class :
A CSS pseudo-class is a keyword, preceded by a colon (:), added to the end of selectors to specify you want to style the selected elements, and only when they are in certain state. For example, you might want to style an element only when it is being hovered over by the mouse pointer, or a checkbox when it is disabled or checked, or an element that is the first child of its parent in the DOM tree.
Examples:
:active
:checked
:nth-child()
:first
:hover
Pseudo-elements ::
Pseudo-elements are very much like pseudo-classes, but they have differences. They are keywords, this time preceded by two colons (::), that can be added to the end of selectors to select a certain part of an element.
Examples:
::after
::before
::first-letter
::first-line
::selection
::backdrop
As stated by #stephanmg:
In practice ::before is used as :before and ::after is used as :after
because of browser compatibility. Both are pseudo-elements, but may
look like pseudo classes. This might be confusing if you read CSS
code.
Pseudo-classes :
it is applied automatically by the browser
depending on the position of the element or its interactive state.
For Example :
E:hover Matches elements of type E when the cursor is
hovering over it.
Pseudo-elements :
It is applies styles to content
based on its position in the HTML hierarchy.
For Example :
E::first-letter This applies a style to the first letter of the first line inside a block-level
element E.
So ,
The CSS3 Selectors specification prefixes pseudo-elements with two colons instead of one.
So, :first–letter becomes ::first-letter and :first-line becomes ::first-line.
IE 8 and earlier don’t understand the double-colon prefix, so you need use
the single-colon versions to avoid styles breaking in older browsers.

CSS selector "*:before" [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

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

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