CSS selector for empty or whitespace
Lots of people missing the point of this question, which I've addressed in the following exposition, but for those just looking for the answer, I'm mirroring the last paragraph here:
Selectors 4 now redefines
:empty
to include elements that contain only whitespace. This was originally proposed as a separate pseudo-class:blank
but was recently retconned into:empty
after it was determined that it was safe to do so without too many sites depending on the original behavior. Browsers will need to update their implementations of:empty
in order to conform to Selectors 4. If you need to support older browsers, you will have to go through the hassle of marking elements containing only whitespace or pruning the whitespace before or after the fact.
While the question depicts a <p>
element containing a handful of regular space characters, which seems like an oversight, it is far more common to see markup where elements contain only whitespace in the form of indentation and blank lines, such as:
<ul class="items">
<li class="item">
<div>
<!-- Some complex structure of elements -->
</div>
</li>
<li class="item">
</li> <!-- Empty, except for a single line break and
indentation preceding the end tag -->
</ul>
Some elements, like <li>
in the above example as well as <p>
, have optional end tags, which can cause unintended side effects in DOM processing as well in the presence of inter-element whitespace. For example, the following two <ul>
elements don't produce equivalent node trees, in particular the first one does not result in a li:empty
in Selectors level 3:
li:empty::before { content: '(empty)'; font-style: italic; color: #999; }
<ul>
<li>
</ul>
<ul>
<li></li>
</ul>
:empty doesn't work if there's blank spaces?
As the others mentioned, this isn't possible with CSS yet.
You can check to see if there's only whitespace with JavaScript however. Here's a simple JS only solution, "empty" divs that match are blue, while divs that have text are red. Updated to add an empty
class to the empty divs, which would allow you to target them easily with the selector .empty
in your CSS.
The JS only "empty" comparison would look like this:
if(element.innerHTML.replace(/^\s*/, "").replace(/\s*$/, "") == "")
And if you're using jQuery it would be a bit easier:
if( $.trim( $(element).text() ) == "" ){
var navs = document.querySelectorAll(".nav-previous");
for( i=0; i < navs.length; i++ ){
if(navs[i].innerHTML.replace(/^\s*/, "").replace(/\s*$/, "") == "") {
navs[i].style.background = 'blue';
navs[i].classList.add( 'empty' );
} else {
navs[i].style.background = 'red';
}
}
.nav-previous {
padding: 10px;
border: 1px solid #000;
}
.nav-previous.empty {
border: 5px solid green;
}
<div class="nav-previous">
</div>
<div class="nav-previous">Not Empty </div>
Whitespace in CSS selectors
All of your conclusions are correct. There are nuances with regard to whitespace in attribute selectors, covered in my answer to this question.
All the exact rules of where whitespace may or may not appear are covered in the grammar. For the purposes of the grammar, the "contextual characters (such as +
and >
)" that you refer to are officially known as combinators. (The term "contextual selector" was first used in CSS1 but hasn't appeared since.)
Remember in addition that any number of contiguous whitespace characters that separate two simple selectors is considered a descendant combinator, which is in fact one reason why whitespace isn't "allowed" around the delimiters for pseudo-elements, pseudo-classes, attribute selectors, class selectors and ID selectors — because it has significance and therefore its presence alters the meaning of the selector.
:not(:empty) with space in CSS
You cant
(unfortunately)
The :empty
selector is the only way in CSS of detecting content, and also proves positive for whitespace:
The :empty pseudo-class represents any element that has no children at
all. Only element nodes and text (including whitespace) are
considered. Comments or processing instructions do not affect whether
an element is considered empty or not.
Dont forget about the separation of concerns, HTML for content, CSS for styling and JS for functionality - as such, you either need to remove the whitespace from your HTML (content) or apply a class depending on its presence, or strip it using JS (functionality).
With that said, elements only containing whitespace should collapse by default, so long as the space in question isnt a non-breaking space
Demo Fiddle
difference between blank and empty pseudo-classes
The :blank pseudo-class builds upon the :empty pseudo-class. Like
:empty, :blank will select elements that contain nothing at all, or
contain only an HTML comment. But, :blank will also select elements
that include whitespace, which :empty will not.
css-tricks :blank
Also, From the W3c Working Draft on selectors level 4:
The :blank pseudo-class is identical to the :empty pseudo-class,
except that it additionally excludes characters affected by whitespace
processing [CSS3TEXT] when determining whether an element is empty.
Example:
For example, the following element matches :blank, but not :empty,
because it contains at least one linebreak, and possibly other
whitespace:
<p>
</p>
White space and selectors
For this cases I prefer using css selectors because of its minimalistic syntax:response.css("p.text-nowrap.hidden-xs::text")
Also google chrome developer tools displays css selectors when you observing html code
This makes scraper development much easier
Hiding an element that contains only spaces using CSS
I don't think you can do it with pure CSS.
However with a little JavaScript you can do it.
var allParas = document.getElementsByTagName('p');
//filter by class name if desired...
for(var i=0;i<allParas.length;i++){
if(allParas[i].getElementsByTagName('*').length == 0){
allParas[i].style.display = 'none';
}
}
If you have access to jQuery it is a little easier to do the filtering with their built in selectors.
$('p.sitspagedesc').each(function(){
if($(this).children().length == 0){
$(this).hide();
}
});
Related Topics
CSS Display None and Opacity Animation with Keyframes Not Working
Center Navbar Links Without Brand Pushing It to the Right in Bootstrap 4
How to Add a Margin Between Bootstrap Columns Without Wrapping
Automatically Open <Details> Element on Id Call
Make Flex Item Wrap to the Next Row with Following Items Continuing the Flow
Add Padding to HTML Text Input Field
Pure CSS Hover Show Another Element Possible
Unwanted Auto-Scrolling to Top on Input Focus, with Safari
How to Change Side by Side Divs to Stack on Mobile
How to Use the Same Meta Tag for Opengraph and Schema.Org
Failed to Load Resource, Plugin Handled Load on iOS
How to Set the Thumbnail Image on HTML5 Video
Last-Child:After Not Rendering in Chrome? Pseudo-Element Use Issue
Webkit Opacity Transition Issues with Text
How to Append Leading Zero's to an Ordered Number List? (01 or 001 as Opposed to Just 1)