jQuery / Selector / :empty - Select Elements with No Content
jQuery's :empty selects elements with no child elements or text. Scope it with $("#data td:empty") to fill empty table cells. A visually blank element containing whitespace or a child tag does not match, while an element containing only a comment does.
What counts as empty?
The content described in the jQuery :empty documentation includes text nodes. Indentation and line breaks between tags can therefore matter. These distinctions were checked by running this article's example with jQuery 4.0.0 and 3.7.1.
| Content inside an element | Matches :empty? | Reason |
|---|---|---|
| Nothing | Yes | No child elements or text |
| Spaces, a newline or | No | Whitespace is text content |
| A comment only | Yes | Comments do not count for this test |
| An empty span or br tag | No | A child element exists |
The CSS Selectors Level 3 definition also excludes comments from this decision. A title or class attribute does not make an element nonempty. Conversely, hiding a child with display:none does not remove that child from the structure. Do not infer emptiness solely from appearance.
Complete example: fill empty table cells
Save the entire code as UTF-8 in empty-demo.html and open it in a browser. No package installation is needed, but an internet connection is required to load jQuery from the Content Delivery Network (CDN). The example pins the official distribution to jQuery 4.0.0.
blank is genuinely empty, spaces contains three spaces, and comment contains only a comment. The span in nested and br in break are children even without visible text. The output and controls sit outside the table being selected.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Empty table cells</title>
<style>
body { font: 16px/1.6 sans-serif; margin: 24px; }
table { border-collapse: collapse; width: 100%; max-width: 600px; }
td { border: 1px solid #aaa; padding: 16px; min-width: 80px; }
.is-empty { background: #fff0b3; }
button { margin: 16px 8px 0 0; padding: 8px; }
</style>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
<h1>Empty table cells</h1>
<table id="data">
<tr><td id="blank"></td><td id="spaces"> </td></tr>
<tr><td id="comment"><!-- note --></td><td id="text">Hello</td></tr>
<tr><td id="nested"><span></span></td><td id="break"><br></td></tr>
</table>
<button type="button" id="fill">Fill empty cells</button>
<button type="button" id="reset">Reset</button>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
function render() {
const $empty = $("#data td:empty");
$("#data td").removeClass("is-empty");
$empty.addClass("is-empty");
const ids = $empty.map((_, cell) => cell.id).get().join(", ");
$("#result").text(`${ids || "none"} | ${$empty.length}`);
}
$("#fill").on("click", function () {
$("#data td:empty").text("N/A");
render();
});
$("#reset").on("click", function () {
$("#blank, #comment").empty();
render();
});
render();
});
</script>
</body>
</html>
Initially, the result paragraph displays the following and the blank and comment cells are highlighted yellow:
blank, comment | 2
Observe the changes and reset the example
- Press Fill empty cells. N/A is inserted into the two matching cells. A fresh selection produces
none | 0. - Check spaces, nested and break. Their whitespace or child elements prevent them from being filled.
- Press Reset. The contents of blank and comment are removed and both match again. This resets only those two demonstration cells; it does not restore the original comment itself.
.text("N/A") inserts a display string. render first removes the highlight class from all table cells, then adds it only to the currently empty cells. This avoids leaving a stale highlight on cells that have just been filled. Verify both the operation and its displayed state.
Scope the selector and query again after changes
Prefer the targeted $("#data td:empty") to the document-wide $(":empty"). The scope avoids accidentally selecting empty elements elsewhere, including span and br. After opening the example or pressing Reset, run this partial code in the browser's developer console to inspect the current count and IDs:
const $empty = $("#data td:empty");
console.log($empty.length);
console.log($empty.map((_, cell) => cell.id).get().join(", "));
2
blank, comment
A jQuery selection is not a live list that automatically refreshes after document changes. If you retain $empty and fill the cells, the stored object's length remains 2. Run the selector again to count the cells that are empty now. That is why render creates a new selection on every call.
Distinguish :empty, .empty(), :parent and form values
:empty is a selection condition. The .empty() method removes the children and text of selected elements while leaving those elements themselves, making it suitable for the Reset button. The opposite condition, :parent, selects elements with child elements or text. It is separate from the .parent() method, which moves to an element's parent.
An input can match :empty even when its value is JB because its value is not child content. Read the current value with .val() when checking whether a user entered anything, then compare it with an empty string. Whether whitespace-only input counts as blank is a separate policy. Structural emptiness and an empty input value need different checks.
If nothing happens, use the developer tools' Network panel to check whether jQuery loaded, and look for errors such as $ is not defined in Console. Also verify that the IDs in the HTML and selector agree and that editing did not insert whitespace between the supposedly empty cell's tags.




