Anatomy of the DOM - Web APIs | MDN Skip to main content Skip to search MDN HTML HTML: Markup language HTML reference Elements Global attributes Attributes See all… HTML guides Responsive images HTML cheatsheet Date & time formats See all… Markup languages SVG MathML XML CSS CSS: Styling language CSS reference Properties Selectors At-rules Values See all… CSS guides Box model Animations Flexbox Colors See all… Layout cookbook Column layouts Centering an element Card component See all… JavaScriptJS JavaScript: Scripting language JS reference Standard built-in objects Expressions & operators Statements & declarations Functions See all… JS guides Control flow & error handing Loops and iteration Working with objects Using classes See all… Web APIs Web APIs: Programming interfaces Web API reference File system API Fetch API Geolocation API HTML DOM API Push API Service worker API See all… Web API guides Using the Web animation API Using the Fetch API Working with the History API Using the Web speech API Using web workers All All web technology Technologies Accessibility HTTP URI Web extensions WebAssembly WebDriver See all… Topics Media Performance Privacy Security Progressive web apps Learn Learn web development Frontend developer course Getting started modules Core modules MDN Curriculum Check out the video course from Scrimba, our partner Learn HTML Structuring content with HTML module Learn CSS CSS styling basics module CSS layout module Learn JavaScript Dynamic scripting with JavaScript module Tools Discover our tools Playground HTTP Observatory Border-image generator Border-radius generator Box-shadow generator Color format converter Color mixer Shape generator About Get to know MDN better About MDN Advertise with us Community MDN on GitHub Blog Toggle sidebar Web Web APIs Document Object Model (DOM) Anatomy of the DOM Theme OS default Light Dark English (US) Remember language Learn more Deutsch English (US) 日本語 Anatomy of the DOM The DOM represents an XML or HTML document as a tree. This page introduces the basic structure of the DOM tree and the various properties and methods used to navigate it. To begin with, we need to introduce some concepts related to trees. A tree is a data structure made up of nodes. Each node holds some data. The nodes are organized in a hierarchical way—every node has a single parent node (except for the root node, which has no parent), and an ordered list of zero or more child nodes. Now we can define the following: A node with no parent is called the root of the tree. A node with no children is called a leaf. Nodes that share the same parent are called siblings. Siblings belong to the same child node list of their parent, so they have a well-defined order. If we can go from node A to node B by repeatedly following parent links, then A is a descendant of B, and B is an ancestor of A. Nodes in a tree are listed in tree order by first listing the node itself, then recursively listing each of its child nodes in order (preorder, depth-first traversal). And here are a few important properties of trees: Every node is associated with a unique root node. If node A is the parent of node B, then node B is a child of node A. Cycles are not allowed: no node can be an ancestor or descendant of itself. In this article The Node interface and its subclasses Data of each node Element and its attributes Working with the element tree Comparing nodes Summary The Node interface and its subclasses All nodes in the DOM are represented by objects that implement the Node interface. The Node interface embodies many of the previously defined concepts: The parentNode property returns the parent node, or null if the node has no parent. The childNodes property returns a NodeList of the child nodes. The firstChild and lastChild properties return the first and last elements of this list, respectively, or null if there are no children. The getRootNode() method returns the root of the tree that contains the node, by repeatedly following parent links. The hasChildNodes() method returns true if it has any child nodes, i.e., it is not a leaf. The previousSibling and nextSibling properties return the previous and next sibling nodes, respectively, or null if there is no such sibling. The contains() method returns true if a given node is a descendant of the node. The compareDocumentPosition() method compares two nodes by tree order. The Comparing nodes section discusses this method in more detail. You rarely work with plain Node objects—instead, all objects in the DOM implement one of the interfaces that inherit from Node, which represent additional semantics in the document. The node types restrict what data they contain, and what children types are valid. Consider how the following HTML document is represented in the DOM: html <!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <h1>Hello, world!</h1> <p>This is a paragraph.</p> </body> </html> It produces the following DOM tree: The root of this DOM tree is a Document node, which represents the entire document. This node is exposed globally as the document variable. This node has two important child nodes: An optional DocumentType node representing the doctype declaration. In our case, there is one. This node is also accessible via the doctype property of the Document node. An optional Element node representing the root element. For HTML documents (such as our case), this is typically the HTMLHtmlElement. For SVG documents, this is typically the SVGSVGElement. This node is also accessible via the documentElement property of the Document node. The DocumentType node is always a leaf node. The Element node is where most of the document content is represented. Each element under it, such as <head>, <body>, and <p>, is also represented by an Element node. In fact, each is a subclass of Element specific to that tag name, defined in the HTML specification, such as HTMLHeadElement and HTMLBodyElement, with additional properties and methods to represent the semantics of that element, but here we focus on the common behaviors of the DOM. The Element nodes can have other Element nodes as children, representing nested elements. For example, the <head> element has three children: two <meta> elements and a <title> element. Additionally, elements can also have Text nodes and CDATASection nodes as children, representing text content. For example, the <p> element has a single child, a Text node containing the string "This is a paragraph.". Text nodes and CDATASection nodes are always leaf nodes. All nodes that can have children (Document, DocumentFragment, and Element) allow two types of children: Comment and ProcessingInstruction nodes. These nodes are always leaf nodes. Each element, in addition to having child nodes, can also have attributes, represented as Attr nodes. Attr extend the Node interface, but they are not part of the main tree structure, because they are not the child of any node and their parent node is null. Instead, they are stored in a separate named node map, accessible via the attributes property of the Element node. The Node interface defines a nodeType property that indicates the type of the node. To summarize, we introduced the following node types: Node type nodeType value Valid children (besides Comment and ProcessingInstruction) Document Node.DOCUMENT_NODE (9) DocumentType, Element DocumentType Node.DOCUMENT_TYPE_NODE (10) None Element Node.ELEMENT_NODE (1) Element, Text, CDATASection Text Node.TEXT_NODE (3) None CDATASection Node.CDATA_SECTION_NODE (4) None Comment Node.COMMENT_NODE (8) None ProcessingInstruction Node.PROCESSING_INSTRUCTION_NODE (7) None Attr Node.ATTRIBUTE_NODE (2) None Note: You may notice we skipped some node types here. The Node.ENTITY_REFERENCE_NODE (5), Node.ENTITY_NODE (6), and Node.NOTATION_NODE (12) values are no longer used, while the Node.DOCUMENT_FRAGMENT_NODE (11) value will be introduced in Building and updating the DOM tree. Data of each node Each node type has its own way of representing the data it holds. The Node interface itself defines three properties related to data, summarized in the following table: Node type nodeName nodeValue textContent Document "#document" null null DocumentType Its name (e.g., "html") null null Element Its tagName (e.g., "HTML", "BODY") null Concatenation of all its text node descendants in tree order Text "#text" Its data Its data CDATASection "#cdata-section" Its data Its data Comment "#comment" Its data Its data ProcessingInstruction Its target Its data Its data Attr Its name Its value Its value Document The Document node does not hold any data itself, so its nodeValue and textContent are always null. Its nodeName is always "#document". The Document does define some metadata about the document, coming from the environment (for example, the HTTP response that served the document): The URL and documentURI properties return the document's URL. The characterSet property returns the character encoding used by the document, such as "UTF-8". The compatMode property returns the rendering mode of the document, either "CSS1Compat" (standards mode) or "BackCompat" (quirks mode). The contentType property returns the media type of the document, such as "text/html" for HTML documents. DocumentType A DocumentType in the document looks like this: xml <!doctype name PUBLIC "publicId" "systemId"> There are three parts you can specify, which correspond to the three properties of the DocumentType node: name, publicId, and systemId. For HTML documents, the doctype is always <!doctype html>, so the name is "html" and both publicId and systemId are empty strings. Element An Element in the document looks like this: html <p class="note" id="intro">This is a paragraph.</p> In addition to the contents, there are two parts you can specify: the tag name and the attributes. The tag name corresponds to the tagName property of the Element node, which is "P" in this case (note that it is always in uppercase for HTML elements). The attributes correspond to the Attr nodes stored in the attributes property of the Element node. We will discuss attributes in more detail in the Element and its attributes section. The Element node does not hold any data itself, so its nodeValue is always null. Its textContent is the concatenation of all its text node descendants in tree order, which is "This is a paragraph." in this case. For the following element: html <div>Hello, <span>world</span>!</div> The textContent is "Hello, world!", concatenating the text node "Hello, ", the text node "world" inside the <span> element, and the text node "!". CharacterData Text, CDATASection, Comment, and ProcessingInstruction all inherit from the CharacterData interface, which is a subclass of Node. The CharacterData interface defines a single property, data, which holds the text content of the node. The data property is also used to implement the nodeValue and textContent properties of these nodes. For Text and CDATASection, the data property holds the text content of the node. In the following document (note that we use an SVG document, because HTML does not allow CDATA sections): svg <text>Some text</text> <style><![CDATA[h1 { color: red; }]]></style> The text node inside the <text> element has "Some text" as data, and the CDATA section inside the <style> element has "h1 { color: red; }" as data. For Comment, the data property holds the content of the comment, starting after the <!-- and ending before the -->. For example, in the following document: html <!-- This is a comment --> The comment node has " This is a comment " as data. For ProcessingInstruction, the data property holds the content of the processing instruction, starting after the target and ending before the ?>. For example, in the following document: xml <?xml-stylesheet type="text/xsl" href="style.xsl"?> The processing instruction node has 'type="text/xsl" href="style.xsl"' as data, and "xml-stylesheet" as its target. In addition, the CharacterData interface defines the length property, which returns the length of the data string, and the substringData() method, which returns a substring of the data. Attr For the following element: html <p class="note" id="intro">This is a paragraph.</p> The <p> element has two attributes, represented by two Attr nodes. Each attribute consists of a name and a value, corresponding to the name and value properties. The first attribute has "class" as name and "note" as value, while the second attribute has "id" as name and "intro" as value. Element and its attributes As previously mentioned, the attributes of an Element node are represented by Attr nodes, which are stored in a separate named node map, accessible via the attributes property of the Element node. This NamedNodeMap interface defines three important properties: length, which returns the number of attributes. item() method, which returns the Attr at a given index. getNamedItem() method, which returns the Attr with a given name. The Element interface also defines several methods to work with attributes directly, without needing to access the named node map: element.getAttribute(name) is equivalent to element.attributes.getNamedItem(name).value, if the attribute exists. element.getAttributeNode(name) is equivalent to element.attributes.getNamedItem(name). element.hasAttribute(name) is equivalent to element.attributes.getNamedItem(name) !== null. element.getAttributeNames() returns an array of all attribute names. element.hasAttributes() is equivalent to element.attributes.length > 0. You can also access the owner element of an attribute via the ownerElement property of the Attr node. There are two special attributes, id and class, which have their own properties on the Element interface: id and className, that reflect the value of the corresponding attribute. In addition, the classList property returns a DOMTokenList representing the list of classes in the class attribute. Working with the element tree Because Element nodes form the backbone of the document structure, you can specifically traverse the element nodes, skipping other nodes (such as Text and Comment). For all nodes, the parentElement property returns the parent node if it is an Element, or null if the parent is not an Element (for example, if the parent is a Document). This is in contrast to parentNode, which returns the parent node regardless of its type. For Document, DocumentFragment, and Element, the children property returns an HTMLCollection of only the child Element nodes. This is in contrast to childNodes, which returns all child nodes. The firstElementChild and lastElementChild properties return the first and last elements of this collection, respectively, or null if there are no child elements. The childElementCount property returns the number of child elements. For Element and CharacterData, the previousElementSibling and nextElementSibling properties return the previous and next sibling node that is an Element, or null if there is no such sibling. This is in contrast to previousSibling and nextSibling, which may return any type of sibling node. Comparing nodes There are three important methods that compare nodes: isEqualNode(), isSameNode(), compareDocumentPosition(). The isSameNode() method is legacy. Now, it behaves like the strict equality operator (===), returning true if and only if the two nodes are the same object. The isEqualNode() method compares two nodes structurally. Two nodes are considered equal if they have the same type, the same data, and their child nodes are also equal at each index. In the Data of each node section, we already defined the data relevant for each node type: For Document, there is no data, so only the child nodes need to be compared. For DocumentType, the name, publicId, and systemId properties need to be compared. For Element, the tagName (more accurately, the namespaceURI, prefix, and localName; we will introduce these in the XML namespaces guide) and the attributes need to be compared. For Attr, the name (more accurately, the namespaceURI, prefix, and localName; we will introduce these in the XML namespaces guide) and value properties need to be compared. For all CharacterData nodes (Text, CDATASection, Comment, and ProcessingInstruction), the data property needs to be compared. For ProcessingInstruction, the target property also needs to be compared. The a.compareDocumentPosition(b) method compares two nodes by tree order. It returns a bitmask indicating their relative positions. The possible cases are: Returns 0 if a and b are the same node. If the two nodes are both attributes of the same element node, returns Node.DOCUMENT_POSITION_PRECEDING | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC (34) if a precedes b in the attribute list, or Node.DOCUMENT_POSITION_FOLLOWING | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC (36) if a follows b. If either node is an attribute, the owner element is used for further comparisons. If the two nodes don't have the same root node, returns either Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Node.DOCUMENT_POSITION_PRECEDING (35) or Node.DOCUMENT_POSITION_DISCONNECTED | Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Node.DOCUMENT_POSITION_FOLLOWING (37). Which one is returned is implementation-specific. If a is an ancestor of b (including when b is an attribute of a), returns Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_PRECEDING (10). If a is a descendant of b (including when a is an attribute of b), returns Node.DOCUMENT_POSITION_CONTAINED_BY | Node.DOCUMENT_POSITION_FOLLOWING (20). If a precedes b in tree order, returns Node.DOCUMENT_POSITION_PRECEDING (2). If a follows b in tree order, returns Node.DOCUMENT_POSITION_FOLLOWING (4). Bitmask values are used, so you can use a bitwise AND operation to check for specific relationships. For example, to check if a precedes b, you can do: js if (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_PRECEDING) { // a precedes b } Which accounts for the cases of a and b being attributes of the same element, a being an ancestor of b, and a preceding b in tree order. Summary Here are all the features we've introduced so far. There are a lot, but they are all useful in different scenarios. All nodes in the DOM implement the Node interface. To navigate around the DOM tree: parentNode, childNodes, firstChild/lastChild, hasChildNodes(), getRootNode(), previousSibling/nextSibling. To navigate around the element tree: parentElement, children, firstElementChild/lastElementChild, childElementCount, previousElementSibling/nextElementSibling. The nodeType property indicates the type of the node. The nodeName, nodeValue, and textContent properties provide the data held by the node. The Document node and its two important children: doctype and documentElement. The DocumentType node and its three properties: name, publicId, and systemId. The Element node and its properties: tagName, attributes. The Attr node and its properties: name and value. The CharacterData interface and its property: data. The four CharacterData subclasses: Text, CDATASection, Comment, and ProcessingInstruction. ProcessingInstruction also has the target property. The various ways to work with attributes, including the id, className, and classList properties. The three methods to compare nodes: isEqualNode(), isSameNode(), and compareDocumentPosition(). Help improve MDN Was this page helpful to you? Yes No Learn how to contribute This page was last modified on Oct 20, 2025 by MDN contributors. View this page on GitHub • Report a problem with this content Filter sidebar Clear filter input Document Object Model (DOM) Guides Anatomy of the DOM Attribute reflection Selection and traversal on the DOM tree Building and updating the DOM tree Working with events Interfaces AbortController AbortSignal AbstractRange Attr CDATASection CharacterData Comment CustomEvent Document DocumentFragment DocumentType DOMError DOMException DOMImplementation DOMParser DOMTokenList Element Event EventTarget HTMLCollection MutationObserver MutationRecord NamedNodeMap Node NodeIterator NodeList ProcessingInstruction QuotaExceededError Range ShadowRoot StaticRange Text TreeWalker XMLDocument XPathEvaluator XPathExpression XPathResult XSLTProcessor MDN Your blueprint for a better internet. MDN About Blog Mozilla careers Advertise with us MDN Plus Product help Contribute MDN Community Community resources Writing guidelines MDN Discord MDN on GitHub Developers Web technologies Learn web development Guides Tutorials Glossary Hacks blog Mozilla Website Privacy Notice Telemetry Settings Legal Community Participation Guidelines Portions of this content are ©1998–2026 by individual mozilla.org contributors. Content available under a Creative Commons license.