HTML DOM Node

Understanding DOM nodes and the node tree structure

🌳 What are DOM Nodes?

In the DOM, everything is a node. Elements, text, attributes, and even whitespace are all different types of nodes that form a tree structure.


// Every part of HTML is a node
let element = document.getElementById("myDiv");
console.log(element.nodeType);        // 1 (Element node)
console.log(element.nodeName);        // "DIV"
console.log(element.childNodes.length); // Number of child nodes
                                    

Output:

1
DIV
3

Types of Nodes

📦

Element Node

HTML tags like <div>, <p>

nodeType: 1
nodeName: "DIV"
📝

Text Node

Text content inside elements

nodeType: 3
nodeName: "#text"
🏷️

Attribute Node

Element attributes like id, class

nodeType: 2
nodeName: "class"
💬

Comment Node

HTML comments <!-- -->

nodeType: 8
nodeName: "#comment"

🔹 Node Properties

Every node has properties that describe its type and content:

// Get a node
let paragraph = document.getElementById("myParagraph");

// Node type constants
console.log(Node.ELEMENT_NODE);        // 1
console.log(Node.TEXT_NODE);           // 3
console.log(Node.COMMENT_NODE);        // 8
console.log(Node.DOCUMENT_NODE);       // 9

// Node properties
console.log(paragraph.nodeType);       // 1 (element)
console.log(paragraph.nodeName);       // "P"
console.log(paragraph.nodeValue);      // null (for elements)

// For text nodes
let textNode = paragraph.firstChild;
if (textNode && textNode.nodeType === 3) {
    console.log(textNode.nodeType);     // 3
    console.log(textNode.nodeName);     // "#text"
    console.log(textNode.nodeValue);    // The actual text content
}

// Check node type
function getNodeTypeDescription(node) {
    switch(node.nodeType) {
        case 1: return "Element";
        case 3: return "Text";
        case 8: return "Comment";
        case 9: return "Document";
        default: return "Other";
    }
}

Output:

1
3
8
9
1
P
null
3
#text
This is paragraph text

🔹 Node Relationships

Nodes are connected in a tree structure with parent-child relationships:

let element = document.getElementById("container");

// Parent relationships
console.log(element.parentNode);       // Parent node
console.log(element.parentElement);    // Parent element (excludes non-element parents)

// Child relationships
console.log(element.childNodes);       // All child nodes (includes text nodes)
console.log(element.children);         // Only element children
console.log(element.firstChild);       // First child node
console.log(element.lastChild);        // Last child node
console.log(element.firstElementChild); // First element child
console.log(element.lastElementChild);  // Last element child

// Sibling relationships
console.log(element.nextSibling);      // Next sibling node
console.log(element.previousSibling);  // Previous sibling node
console.log(element.nextElementSibling); // Next element sibling
console.log(element.previousElementSibling); // Previous element sibling

// Count nodes
console.log(element.childNodes.length);    // Total child nodes
console.log(element.children.length);      // Element children only

// Example HTML structure:
// <div id="container">
//   <p>First paragraph</p>
//   <p>Second paragraph</p>
// </div>

Output:

[object HTMLBodyElement]
[object HTMLBodyElement]
[object NodeList] (length: 5)
[object HTMLCollection] (length: 2)
[object Text] (whitespace)
[object Text] (whitespace)
[object HTMLParagraphElement]
[object HTMLParagraphElement]
5
2

🔹 Working with Text Nodes

Text nodes contain the actual text content of elements:

// Create and work with text nodes
let paragraph = document.createElement("p");
let textNode = document.createTextNode("Hello World!");

// Add text node to element
paragraph.appendChild(textNode);

// Access text node content
console.log(textNode.nodeValue);       // "Hello World!"
console.log(textNode.textContent);     // "Hello World!"

// Modify text node
textNode.nodeValue = "Updated text!";

// Get text from element
let existingP = document.getElementById("myText");
let firstTextNode = existingP.firstChild;

if (firstTextNode && firstTextNode.nodeType === Node.TEXT_NODE) {
    console.log("Text content:", firstTextNode.nodeValue);
    firstTextNode.nodeValue = "New text content";
}

// Remove whitespace text nodes
function removeWhitespaceNodes(element) {
    let child = element.firstChild;
    while (child) {
        let nextChild = child.nextSibling;
        if (child.nodeType === Node.TEXT_NODE && 
            child.nodeValue.trim() === "") {
            element.removeChild(child);
        }
        child = nextChild;
    }
}

// Split text nodes
let longText = document.createTextNode("This is a long text");
let splitNode = longText.splitText(10); // Split at position 10
console.log(longText.nodeValue);        // "This is a "
console.log(splitNode.nodeValue);       // "long text"

Output:

Hello World!
Hello World!
Text content: Original text
This is a
long text

🔹 Node Manipulation Methods

Methods to add, remove, and modify nodes:

let container = document.getElementById("container");

// Create nodes
let newDiv = document.createElement("div");
let newText = document.createTextNode("New content");
let newComment = document.createComment("This is a comment");

// Add nodes
container.appendChild(newDiv);              // Add to end
container.insertBefore(newDiv, container.firstChild); // Insert at beginning

// Clone nodes
let clonedDiv = newDiv.cloneNode(false);    // Shallow clone (no children)
let deepClone = newDiv.cloneNode(true);     // Deep clone (with children)

// Remove nodes
container.removeChild(newDiv);              // Remove specific child
newDiv.remove();                           // Remove self (modern browsers)

// Replace nodes
let oldNode = document.getElementById("oldElement");
let newNode = document.createElement("span");
newNode.textContent = "Replacement";
container.replaceChild(newNode, oldNode);

// Check if node contains another
let parent = document.getElementById("parent");
let child = document.getElementById("child");
console.log(parent.contains(child));       // true/false

// Compare nodes
let node1 = document.getElementById("first");
let node2 = document.getElementById("second");
console.log(node1.isEqualNode(node2));     // Compare structure and content
console.log(node1.isSameNode(node2));      // Compare if same object

// Normalize text nodes (combine adjacent text nodes)
container.normalize();

Output:

true
false
false
Adjacent text nodes combined

🔹 Traversing the Node Tree

Navigate through the DOM tree structure:

// Recursive function to traverse all nodes
function traverseNodes(node, callback) {
    callback(node);
    
    // Process all child nodes
    for (let i = 0; i < node.childNodes.length; i++) {
        traverseNodes(node.childNodes[i], callback);
    }
}

// Example: Find all text nodes
function findAllTextNodes(element) {
    let textNodes = [];
    
    function traverse(node) {
        if (node.nodeType === Node.TEXT_NODE) {
            textNodes.push(node);
        }
        for (let child of node.childNodes) {
            traverse(child);
        }
    }
    
    traverse(element);
    return textNodes;
}

// Example: Count different node types
function countNodeTypes(element) {
    let counts = {
        elements: 0,
        text: 0,
        comments: 0,
        other: 0
    };
    
    traverseNodes(element, function(node) {
        switch(node.nodeType) {
            case Node.ELEMENT_NODE:
                counts.elements++;
                break;
            case Node.TEXT_NODE:
                counts.text++;
                break;
            case Node.COMMENT_NODE:
                counts.comments++;
                break;
            default:
                counts.other++;
        }
    });
    
    return counts;
}

// Usage
let body = document.body;
let textNodes = findAllTextNodes(body);
let nodeCounts = countNodeTypes(body);

console.log("Text nodes found:", textNodes.length);
console.log("Node counts:", nodeCounts);

Output:

Text nodes found: 15
Node counts: {elements: 42, text: 15, comments: 2, other: 0}

🧠 Test Your Knowledge

What nodeType value represents an element node?