jQuery .contents() vs .children() Explained
This article breaks down the jQuery .contents() and
.children() methods, exploring what
.contents() does, how both methods traverse the DOM, and
their crucial functional differences. Readers will learn how these
methods handle text nodes, HTML elements, and iframes, allowing
developers to choose the right traversal method for their specific use
cases.
Understanding the jQuery .contents() Method
The .contents() method retrieves all immediate children
of each element in the matched set. Unlike most DOM traversal methods in
jQuery, .contents() does not limit itself strictly to HTML
element nodes (like <div>, <p>, or
<span>). Instead, it returns:
- Element nodes: Standard HTML elements.
- Text nodes: Free text, whitespace, and line breaks directly inside the parent element.
- Comment nodes: HTML comments located within the element.
- Iframe documents: The document node inside an
<iframe>, provided the iframe follows the same-origin policy.
Because of this behavior, .contents() is the primary
jQuery method used to target raw text inside a container or inspect the
DOM of an embedded iframe.
Understanding the jQuery .children() Method
The .children() method traverses one single level down
the DOM tree to retrieve the immediate child elements of the matched
set.
Its defining characteristic is that it filters out everything that is
not an element node. Text nodes, whitespace, and comments are entirely
ignored. Additionally, .children() accepts an optional
selector expression (for example,
$('div').children('.active')), allowing developers to
narrow down the retrieved child elements immediately.
Key Differences Between .contents() and .children()
While both methods search one level deep into the DOM tree, their scope and capabilities diverge in three main areas:
1. Handling of Text and Comment Nodes
.children(): Strictly targets element nodes (nodeType === 1). Any loose text, whitespace, or comments directly inside the parent are discarded..contents(): Targets all child nodes regardless of type, including element nodes (nodeType === 1), text nodes (nodeType === 3), and comment nodes (nodeType === 8).
2. Built-in Selector Filtering
.children([selector]): Accepts an optional selector string to filter elements directly during the traversal..contents(): Does not accept arguments. To filter the nodes returned by.contents(), developers must chain additional methods like.filter().
3. Iframe Traversal
.children(): Cannot penetrate into the document of an<iframe>. Calling.children()on an iframe element yields nothing..contents(): When called on an<iframe>, it returns the iframe's internaldocumentobject, allowing scripts to query and manipulate elements within that frame (e.g.,$('iframe').contents().find('body')).
Practical Comparison Example
Consider the following HTML structure:
<div id="container">
Hello World!
<!-- This is a comment -->
<span>Featured Item</span>
</div>If you query the #container element using both
methods:
// Using .children()
const childElements = $('#container').children();
console.log(childElements.length); // Output: 1 (only the <span>)
// Using .contents()
const allContents = $('#container').contents();
console.log(allContents.length); // Output: 4 (text node, comment, text node, and span)In this scenario, .children() returns only the single
<span> element. Conversely, .contents()
captures the leading text node containing "Hello World!", the HTML
comment, the whitespace text nodes, and the <span>
element.
When to Use Which Method
Use .children() when working exclusively with standard
HTML markup, building layout logic, or filtering components by classes
or tags.
Use .contents() when accessing or modifying raw text
that is not wrapped in an HTML tag, wrapping loose text nodes, stripping
comments, or manipulating the contents of a same-origin iframe.