Element
The element surface: identity, attributes, content, classList, element-only traversal, and insertion. All setters and mutators are guarded and throw NoModificationAllowedError on a read-only document. Tree mutation shared with every node (appendChild, remove, …) lives on the Node page.
Identity
Read-only accessors describing the element:
| Accessor | Value |
|---|---|
tagName |
Tag name — uppercased for no-namespace elements (HTML-parsed and createElement), verbatim for createElementNS. |
localName |
The part after the first :. |
prefix |
The namespace prefix, or null. |
namespaceURI |
The resolved namespace URI (stored, or walked from an ancestor xmlns:*), or null. |
id |
The id attribute, or "". |
className |
The whole class attribute, or "". |
const el = document.querySelector("svg > g");
el.tagName; // "G" (or verbatim if created with createElementNS)
el.id; // "" when absent
Attributes
A set of high-frequency elements expose reflected IDL properties that read and write the matching content attribute — a.href, img.src/img.alt, input.type/input.value/input.required, and other form-control properties (see Reflected IDL attributes below and per-tag interfaces). Elements outside that set are a plain HTMLElement with no reflected properties. Either way, the getAttribute / setAttribute methods below work on every element and are the general mechanism.
getAttribute
getAttribute(name) → the value, or null when absent.
const href = link.getAttribute("href");
hasAttribute
hasAttribute(name) → boolean.
if (input.hasAttribute("required")) { /* … */ }
setAttribute
setAttribute(name, value) — sets or replaces the attribute. Guarded.
link.setAttribute("rel", "noopener");
removeAttribute
removeAttribute(name) — removes it; a no-op when absent. Guarded.
input.removeAttribute("disabled");
getAttributeNS / setAttributeNS / removeAttributeNS
The namespaced variants. getAttributeNS(ns, localName) resolves the URI to an in-scope xmlns: prefix, then reads prefix:localName (null if no in-scope prefix maps the URI). setAttributeNS(ns, qualifiedName, value) stores the attribute under qualifiedName verbatim — the ns argument is used only to validate the qualified name (throws NamespaceError if malformed). removeAttributeNS(ns, localName) resolves URI → prefix and removes prefix:localName.
el.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "#icon");
el.getAttributeNS("http://www.w3.org/1999/xlink", "href"); // "#icon"
Reflected IDL attributes
For a set of high-frequency element interfaces, common IDL properties are reflected: reading the property returns the content attribute (or "" when absent, false for boolean properties), and writing it sets — or, for a falsy boolean, removes — the attribute. They are exactly equivalent to getAttribute/setAttribute on the underlying attribute; use whichever reads better.
const a = document.querySelector("a");
a.href; // reads the href attribute ("" if absent)
a.href = "/next"; // sets it — a.getAttribute("href") === "/next"
const input = document.querySelector("input");
input.required = true; // adds the boolean attribute
input.required; // → true (input.hasAttribute("required"))
Every interface has its own reference page, listing its reflected properties (see Reflected properties: shared semantics below for how numeric/enum/boolean reflection works in general):
† = a deprecated element (WHATWG HTML §16.3 "Other elements, attributes and APIs"); its interface exists only for instanceof / constructor.name and content-attribute reflection fidelity — the tag is obsolete and should not be used in new content. Some interfaces cover more than one tag (blockquote/q, ins/del, the table sections/cells/cols, the six headings h1–h6). video and audio are HTMLMediaElement subclasses: video instanceof HTMLVideoElement and video instanceof HTMLMediaElement both hold, and both inherit the shared HTMLMediaElement properties (so video.autoplay and audio.controls work), while video-only properties like poster are undefined on an audio.
Reflected properties: shared semantics
Numeric IDL attributes (e.g. td.colSpan/rowSpan, ol.start, img/canvas/video width/height, progress.value/max, meter.*) reflect as the browser's coerced number with per-attribute defaults and clamping — e.g. unset td.colSpan is 1. Enumerated IDL attributes (e.g. input.type, form.method, img/iframe loading, referrerPolicy, and the global dir/inputMode/enterKeyHint/autocapitalize on HTMLElement) canonicalize to their keyword with WHATWG missing/invalid defaults — e.g. unset input.type is "text". One enumerated attribute takes a non-standard shape: crossOrigin is a nullable enum — a missing attribute reflects as null, any present value other than "use-credentials" maps to "anonymous", and assigning null removes the attribute. A few attributes reflect as a string even though the WHATWG IDL might suggest otherwise: embed/object width/height, ol.type, area.shape/coords (verbatim, uncanonicalized, case preserved), and the deprecated §16.3 interfaces' numeric-looking attributes (marquee.*). contentEditable (on HTMLElement) is reflected through a bespoke accessor, not the enum path — see its page for the getter/setter shape.
A property is only present on its own interface — img.href is undefined, not an error (see interface scoping). Two intentional divergences: value-like properties (input.value, option.value, textarea.value) reflect the content attribute (the browser's defaultValue), not live editing state, because the server DOM is static; and URL properties (.href, .src) reflect verbatim with no base-URL resolution.
Content
textContent is documented with the Node content members. The HTML-string members below are element-only.
innerHTML
Get returns the serialised child content. Set parses only the assigned string — the document is never re-serialised and re-parsed. Guarded.
section.innerHTML = "<p>Loaded.</p>";
outerHTML
Get returns the element and its children serialised. Set replaces the element within its parent; throws NoModificationAllowedError if the element has no parent. Guarded.
placeholder.outerHTML = "<img src='/logo.svg' alt='Logo'>";
insertAdjacentHTML
insertAdjacentHTML(position, html) — parses html and inserts it at position (case-insensitive): beforebegin, afterbegin, beforeend, afterend. An invalid position throws SyntaxError; beforebegin/afterend on a parentless node are no-ops. Guarded.
list.insertAdjacentHTML("beforeend", "<li>Appended</li>");
classList
element.classList is a live DOMTokenList over the class attribute — the single source of truth (emptying the list removes the attribute). Mutators are guarded. It is iterable ([...classList], Array.from(classList)).
| Member | Behaviour |
|---|---|
add(...tokens) |
Adds tokens (deduped, order preserved). |
remove(...tokens) |
Removes every listed token. |
toggle(token, force?) → boolean |
Adds/removes; force pins the outcome. Returns whether the token is now present. |
replace(old, new) → boolean |
Replaces old with new (set semantics); returns whether a replacement happened. |
contains(token) → boolean |
Membership test. |
item(index) → string / null |
The token at index (negative → null). |
length |
Token count. |
value (get/set) |
The whole class string. |
el.classList.add("active", "highlight");
el.classList.toggle("open"); // → true (now present)
el.classList.replace("active", "done"); // → true
if (el.classList.contains("done")) { /* … */ }
Element traversal
Element-only navigation (skipping text and comment nodes). Each returns an element or null except the count. See Node for the all-kinds accessors (firstChild, nextSibling, …).
| Accessor | Value |
|---|---|
children |
A static NodeList of child elements. |
firstElementChild / lastElementChild |
First / last child element, or null. |
childElementCount |
Number of child elements. |
nextElementSibling / previousElementSibling |
Adjacent sibling element, or null. |
for (const row of table.children) { /* each <tr> */ }
closest
closest(selector) → the nearest inclusive ancestor matching the selector, or null. Receiver-scoped. Invalid selector throws SyntaxError.
const form = submitButton.closest("form");
matches
matches(selector) → boolean. Invalid selector throws SyntaxError.
if (el.matches("a[href^='https://']")) { /* external link */ }
Insertion convenience
The WHATWG convenience mutators. String arguments become text nodes. before/after/replaceWith are no-ops on a detached node. All guarded.
| Method | Behaviour |
|---|---|
append(...nodes) |
Insert at the end of this element's children. |
prepend(...nodes) |
Insert at the start. |
before(...nodes) / after(...nodes) |
Insert as a sibling before / after this element. |
replaceWith(...nodes) |
Replace this element (it detaches but stays live). |
remove() |
Detach this element from its parent. |
heading.after(document.createElement("hr"));
oldBanner.replaceWith("Plain text now"); // string → text node
staleNode.remove();