CSS selector for detecting elements with empty or whitespace-only content

A special selector called :empty allows us to target elements that are entirely devoid of content:

<p></p>

However, in some cases, the element may appear empty due to line breaks or white spaces:

<p>    </p>

In Firefox, a workaround exists using :-moz-only-whitespace:

:empty { width: 300px; height: 15px; background: blue; }
:-moz-only-whitespace { width: 300px; height: 15px; background: orange; }
<p></p>
<p>    </p>
<p>This is paragraph three.</p>

Is there an equivalent solution for other web browsers?

PS: Check out the JSFiddle link

Answer №1

Many individuals seem to be missing the intended focus of this question, but fear not as I will address it in the following detailed explanation. For those who simply seek the answer, I will repeat the crucial information found in the last paragraph:

Selectors 4 has redefined :empty to now encompass elements that solely consist of whitespace characters. Although initially proposed as a distinct pseudo-class called :blank, it has been merged into :empty after careful consideration that it wouldn't disrupt too many existing sites. All browsers must update their implementations of :empty to align with the Selectors 4 specification. When dealing with older browser support, you might find yourself needing to mark elements containing only whitespace or adjust the whitespace content accordingly.


The example presented in the question features a <p> element with several regular space characters, which may appear trivial at first glance. However, it is more commonplace to encounter markup where elements are filled with indents and blank lines, like so:

<ul class="items">
  <li class="item">
    <div>
      <!-- Complicated structure of nested elements -->
    </div>
  </li>
  <li class="item">
  </li> <!-- Appears empty except for a line break and indentation before the closing tag -->
</ul>

Certain elements such as <li>, as shown above, and <p>, possess optional end tags, potentially leading to unintended outcomes during DOM processing when inter-element whitespace is present. For instance, consider how the following two <ul> examples produce differing node structures, particularly absence of a li:empty match under Selectors level 3:

li:empty::before { content: '(empty)'; font-style: italic; color: #999; }
<ul>
  <li>
</ul>
<ul>
  <li></li>
</ul>

Considering that HTML treats inter-element whitespace as transparent by design, it's reasonable to desire styling these elements via CSS without modifying either the HTML itself or its generating application (especially if it entails creating and testing specialized cases). In light of this, Selectors 4 has expanded the definition of :empty to include elements consisting solely of whitespace. Originally introduced as :blank, this change was integrated into :empty given minimal disruption anticipated for existing websites. Therefore, browsers must adapt their handling of :empty to adhere to the Selectors 4 standard, while older browser compatibility entails marking whitespace-containing elements or adjusting them appropriately.

Answer №2

Trick Level 4 into thinking it's empty by using this code snippet:

:not(:has(*)) { /* apply styling here */ }

Answer №3

A remarkable insight was provided by @BoltClock in response to this inquiry, revealing that achieving this task with CSS alone (specifically working with CSS Specification 3 at the moment) is not feasible.

@BoltClock pointed out that elements that are absolutely empty (a somewhat peculiar definition as explained) can be pinpointed using the pseudo selector :empty. This particular pseudo selector is exclusive to CSS 3 and will NOT target elements containing only whitespace as content.

Additionally, @BoltClock mentioned that rectifying elements with solely whitespace as content is typically resolved by fixing the HTML structure, however, it's worth noting that Javascript implementation can also accomplish this.

Important Note: The Javascript solution proposed to address this issue may have a lengthy execution time, therefore, optimizing the raw HTML structure should be prioritized if possible. Failing which, utilizing this script is viable as long as the DOM tree isn't overly complex.

Let's delve into the steps involved in writing the script independently...

Firstly, initiate everything post page load.

This step is self-explanatory. Ensuring the complete loading of the DOM before executing the script is crucial. Simply add an event listener for page load:

window.addEventListener("load", cleanUpMyDOM);

...and prior to that, define a function named cleanUpMyDOM. All subsequent logic will be encapsulated within this function.

Secondly, identify the elements requiring inspection.

In our scenario, we aim to evaluate the entire DOM, however, this approach may potentially overwhelm your page's performance. It might be prudent to restrict the node iteration scope.

The desired nodes can be retrieved using the document.querySelectorAll function. An advantage of this method is its capacity to flatten the DOM tree without necessitating recursive traversal of each node's children.

var nodes = document.querySelectorAll("*");

As aforementioned, extracting ALL DOM nodes could be disadvantageous.

For instance, given my association with WordPress, certain internal pages contain extraneous elements. Fortunately, these are predominantly p elements nested under a div.body element. Consequently, I can optimize my selector to

document.querySelectorAll("div.body p")
, effectively targeting only p elements within my div.body element recursively. This optimization significantly enhances the script's efficiency.

Thirdly, iterate through the nodes to identify empty ones.

An iterative loop should be crafted for the nodes array to examine each node individually. Subsequently, scrutinizing whether a node is devoid of content is essential. If identified as empty, assign a class called blank to it.

It's more or less an improvisation, so feel free to flag any inaccuracies in the code.

for(var i = 0; i < nodes.length; i++){
    nodes[i].innerHTML = nodes[i].innerHTML.trim();
    if(!nodes[i].innerHTML)
        nodes[i].className += " blank";
}

While there may be a neater way to formulate the above loop, this rendition should suffice for the intended purpose.

Lastly, leverage CSS to target the blank elements.

Include the following rule in your stylesheet:

.blank {
    display:none;
}

Voilà! Your "blank" nodes are now concealed.

For those seeking a prompt resolution, here's the finalized script:

function cleanUpMyDOM(){
    var nodes = document.querySelectorAll("*");
    for(var i = 0; i < nodes.length; i++){
        nodes[i].innerHTML = nodes[i].innerHTML.trim();
        if(!nodes[i].innerHTML)
            nodes[i].className += " blank";
    }
}
window.addEventListener("load", cleanUpMyDOM);

If you come across any anomalies in the code, please share your feedback in the comments section below.

Trust this aids you!

P.S. The rationale behind attempting this operation may raise questions, as it appears unconventional. While I discourage this practice, I find myself contemplating its utility due to specific circumstances. Content on my website's pages is generated via a WYSIWYG editor, constantly revised by the marketing team, presenting challenges in managing their errors. Rectifying issues with WordPress's WYSIWYG editor isn't within my purview, yet devising a simplistic script capable of alleviating some burdens seems like a plausible alternative. Ultimately, this serves as a pragmatic approach, alongside educating the support team on handling whitespace during edits.

Answer №4

For those interested in the specific reference: https://drafts.csswg.org/selectors-4/Overview.bs#the-empty-pseudo

In summary:

Note: Previous versions of Selectors did not consider elements with only white space as empty. This was updated to accommodate how white space can be collapsed in HTML and absorbed by DOM text contents, especially for elements without end tags. This allows authors to select elements they perceive as empty using this selector.

Starting from version 4, :empty will now treat spaces as empty:

Nodes like text nodes and entity references with non-zero length data are now considered in determining emptiness. Comments, processing instructions, and other nodes do not impact whether an element is considered empty or not.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Attain three images with precise dimensions using CSS

Having trouble fitting 3 images in the same row? The issue arises when the images have different sizes, causing everything to shift. Any advice on how to address this problem? Thank you. HTML: <div class="first-slot"> <di ...

Utilize orientation detection technology to ascertain the exact placement of an image

On my HTML page, I have a centered header (h1) with a title that displays in portrait mode above an image. When switching to landscape orientation, I want the image to move to the left side of the title. I've experimented with using <br> along ...

Looking for some guidance with Bootstrap column layouts

I'm in the process of creating an address field layout. My goal is to have the State and Country sections positioned on the right side of the city and postal code fields. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3 ...

The <hr> element creating a line beneath a connected div

Currently, I am in the process of designing a website with three main divs all on one page. To visually separate these divs, I have included a subtle horizontal line. The horizontal line between the first and second div looks correct as intended. However ...

Tips for resizing user-uploaded images to fit the required dimensions outlined in the design draft using CSS or JavaScript

Hey everyone! I'm facing an issue but my English isn't great. I'll do my best to explain it thoroughly, and if anything is unclear, please feel free to let me know! So here's the problem: today there's a block for users to upload p ...

Is there a way to align these blocks in a single row?

Having trouble aligning these buttons horizontally. Any suggestions? I've been tinkering with this for a couple of hours now, so decided to seek help here. The desired effect should resemble the image below, but it's not quite there yet. Thank yo ...

Utilize the conditional GET method when including scripts through tags in an HTML webpage

Is it possible to benefit from HTTP conditional requests when including a script in the head section of a page? My goal is to cache dynamically downloaded JavaScript files that are added to the head section using script tags. If this approach isn't fe ...

Problem with automatic saving of workspaces in DBeaver

Currently using DBeaver with Oracle server and encountering a recurring error related to workspace save. I have searched online for a solution, but all results seem to focus on meta data explanations. As someone new to DBeaver, I would greatly appreciate ...

Steps to gather all the images within a directory

Take a look at this demo When you click on the "next" button, new images are loaded from the internet. In my application, all the images are stored in the img/image folder with names like 1.jpg, hi.png, etc. My question is, how can I display these image ...

creating a personalized CSS style rule

Can a custom rule be created in CSS using @media for a parent class to make changes based on the class? <div class="parentGreen"> <ul class="ul1"> <li>1</li> <li>2</li> &l ...

Where could one possibly find the destination of the mysterious <circle>?

I want to implement a simple pulsating animation on a circle svg element. I attempted using a transform: scale(..,..) animation, but it seems to be shifting the entire circle within its container instead of just scaling the element itself. This is the cur ...

Is there a way to modify the title of a website upon entering the webpage and then updating it when moving to a new page?

I'm encountering an issue with changing the website title during two specific processes. Upon entering a webpage, the title is modified using the following code: <script type="text/javascript"> $(document).ready(function() { docum ...

Adjust the background to scroll to the bottom of the image first and then change it to be fixed

Here is the code I have written: body{ margin:0; padding:0; line-height: 1.5em; background-image: url(http://fehlbelichtet.stefanwensing.de/wp-content/uploads/sites/6/2016/04/alte-strasse-endlos.jpg); background-repeat:no-repeat; background-attachment: ...

Is it possible to have Mobile WebKit store the click position?

I am in the process of developing a unique framework specifically designed for WebKit devices. One of the features I have implemented is a series of list views that activate a 'hover' class when users touch them. Below is the jQuery/JavaScript co ...

What is the best way to disregard all pathNames and display my index.php file directly from the root of my website?

After a user clicks on a navigation link on my website, the page is loaded into a content window within the same page using JavaScript. I then utilize HTML 5 to modify the URL and create a history entry, resulting in a URL resembling the one mentioned (). ...

The height of the input element is greater than the size of the font

I am facing an issue with an input element that has a height 2px higher than what I expected. Here is the relevant CSS: .input { font-size: 16px; padding: 15px; border: 1px solid black; border-radius: 3px; width: 400px; } <input class=" ...

Tips for adjusting large resolution images to fit all screen sizes without exceeding the boundaries of the screen

I am in the process of creating a set of HTML pages specifically tailored for iPad Air and iPad Mini. These pages will feature several large images, with dimensions such as 1600x300. However, upon testing in Windows browsers, I encountered an issue where t ...

Fetching data from MySQL using Ajax technology

I need assistance with my form that is supposed to input a name and phone number, fetch data from a MySQL database based on the input values, and display the results. However, when I execute the query using an onclick function, instead of retrieving data f ...

Creating a CSS layout where a square remains confined within another square even as the screen size changes can be achieved by implementing specific styling techniques and

I have a group of squares that I want to resize proportionally when the screen size changes, but they keep overlapping instead HTML <div id="Container"> <div id="smallSquare1">square 1</div> <div id="smallSqu ...

Is there a way to keep track of changes in multiple dropdowns without having to create a separate JavaScript function for each one

I'm looking for a way to dynamically add more dropdowns as my website grows without having to keep adding new functions to the JavaScript code. Is there a solution for this? Currently, I can add additional functions to the JavaScript like this: ...