Can CSS :not selector target :before and :after selectors
As per W3C Spec:
The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
As you can see from the above statements, :not()
takes in only a simple selector as argument and pseudo-elements do not fall under the simple selector category. Hence, no, you cannot achieve what you are trying in the way you are trying.
One way to hide the element's default content but get the pseudo-element's content to be displayed would be to set font-size: 0px
on the element and then over-ride it to the required size within the pseudo-element's selector like in the below snippet:
a.button:before { content: "Show Text"; font-size: 16px;}a.button { font-size: 0px;}
<a href="#" class="button">Hide Text</a>
Do not style pseudo-class :before/:after
There is no need for something like :not(:before)
. The #main
selector does that already. To see this, set a non-inheritable property like border
:
#main { border: 1px solid; }
This will draw a border around main. It will not draw another border around the generated content. So the selector targets #main
only. Your generated content has a transparent background (default).
The problem is rather that the generated content lives inside an anonymous box inside #main
:
+-------------+
| +-----+ |
| | foo | bar |
| +-----+ |
+-------------+
Basically, this is the same situation as
<div id="main">
<span class="before">foo</span>
bar
</div>
You can easily see that it's not possible to add a background to the word bar only, because #main
's background will shine through the span. If you use #main:not(.before)
as a selector, this will change absolutely nothing.
All you can do is overwrite this by adding a white background to .before
. Or insert a span
around bar, as suggested in another answer.
Other properties like font
are subject to inheritance, so technically the cause of the problem is different, but the solution is the same.
Is there a CSS selector for text nodes?
Text nodes cannot have margins or any other style applied to them, so anything you need style applied to must be in an element. If you want some of the text inside of your element to be styled differently, wrap it in a span
or div
, for example.
Can I target a :before or :after pseudo-element with a sibling combinator?
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.
Why use * selector in combination with *::before and *::after
See these two JSFiddles:
http://jsfiddle.net/86gc1w6f/
http://jsfiddle.net/gwbp2vpL/1/
Or try these snippets:
CSS:
* {
box-sizing: content-box;
}
p {
position: relative;
width: 200px;
border: 10px solid rgba(255, 0, 0, 0.5);
}
p::after {
position: absolute;
right: -100px;
top: -10px;
width: 100px;
height: 30px;
border: 10px solid rgba(0, 0, 255, 0.5);
content: '';
}
HTML:
<p>
A paragraph
</p>
Changing the box-sizing between content-box
and border-box
only alters the size of the paragraph, not it's ::after
element. As others have noted, this is because they are, as named, pseudo elements and must be targeted separately.
It would appear that * does not target psuedo-elements (which as @Harry points out, is as per the CSS specification)
CSS Selector for adding content through :after / :before when HTML element is missing
This won't be possible without the functionality of the :blank
pseudo-class, I'm afraid.1
There are only two possible places you can insert a ::before
pseudo-element in your scenario: in the ul
, or in a li
. Since you want to insert the generated content only when no li
elements are present, that leaves you only with ul
.
Although ::before
and ::after
are inserted before and after an element's descendant elements respectively, you can't target them relative to those descendant elements with a sibling combinator, and pseudo-elements currently do not support structural pseudo-classes. Which means, in other words, you won't be able to say "prevent ul::before
from generating content in the presence of one or more li
elements", nor can you apply the :only-child
pseudo-class to ul::before
.
In a situation where one can use :empty
, it's as simple as
ul:empty::before { content: 'abc'; }
but since you cannot use :empty
for the reasons you have given, if you really cannot prevent the whitespace from being generated (e.g. if the content is coming from a WYSIWYG editor or some other transformation that may result in leftover whitespace) you'll have to add a class to any ul
elements with no children.
1 A recent revision to selectors-4 proposes subsuming the functionality of :blank
into :empty
instead, but that likewise is new and requires the cooperation of implementers.
Related Topics
CSS, Transparent Text with Opaque Background
:After,: Before Issues in Internet Explorer 11
Chrome Does Not Re-Calculate Width When Height Changes
How to Simply Add a CSS File to Change The Background Color for My Shiny App
Can The CSS: Part Pseudo-Selector Be Used to Style Nested Web Components
Bundletable.Enableoptimizations True Breaks Jquery-Ui All.CSS
Issue with: Global() CSS-Module Selectors Not Being Pure in Nextjs
CSS Selector for Only Two Classes and No Others
How to Style: Root Without !Important Using Proper Specificity
Resource Interpreted as Stylesheet But Transferred with Mime Type Text Plain Issue
Selenium Webdriver CSS Selector Help - for Selecting Date
CSS to Remove Text Shadow on Select/Highlight Text (Mozilla)
Why Doesn't Blur(0) Remove All Text Blur in Webkit/Chrome on Retina Screens
Lesscss - Ie Gradient Filter with Variables and Lighten