Element
An Element represents an HTML element. Elements come from two distinct sources, which determines whether they are immutable or mutable.
Two kinds of element
Queried elements
A queried element comes from the document store via a CSS selector expression. Queried elements are immutable — they are snapshots of what the database holds at the time the expression is evaluated.
${h1} // List of all h1 elements
${h1}.first() // First h1 element
${[itemprop="price"]}.last()
${.card}.at(2)
CSS selector expressions always produce a List. Use .first(), .last(), or .at(n) to extract a single element.
Constructed elements
A constructed element is built in the expression itself using new syntax. Constructed elements are mutable — you can call setter methods on them and append children to them before they are used.
new p {}
new h1 { text: "Welcome" }
new div.card[aria-hidden="true"] {}
See Constructing HTML for a full tutorial and Syntax for the complete grammar.
Element.fromString(html)
A static method that parses an HTML string into a constructed element. An alternative to new syntax when the markup is already available as a string. Throws a type error if the string is empty or cannot be parsed as an element.
Returns: constructed element
Element.fromString("<p>hello</p>").getHTML()
// "hello"
Element.fromString("")
// TypeError
Getting data (both kinds)
These methods work on both queried and constructed elements.
.text()
Returns the text content of the element — the concatenation of all descendant text nodes, with no HTML markup.
Returns: string or null
${h1}.first().text()
${[itemprop="name"]}.first().text()
Returns null when the element has no text content.
.value()
Returns the microdata value of the element, following the WHATWG Microdata specification rules for which attribute holds the meaningful value:
| Element | Value attribute |
|---|---|
<a>, <area>, <link> |
href |
<audio>, <embed>, <iframe>, <img>, <source>, <track>, <video> |
src |
<object> |
data |
<meta> |
content |
<data>, <meter> |
value |
<time> |
datetime |
| All others | text content |
The value is returned verbatim — text content is not trimmed, so leading and trailing whitespace is preserved (use .text() and trim it yourself if you want a cleaned string). An element from the table above that is missing its value attribute — for example an <a> with no href — yields an empty string "", not its text content; only <time> falls back to its text when datetime is absent. A text-content element (the “All others” row) whose text is empty yields null — empty text is treated as absent. This matches the value used by uniqueness and reference constraints, so a script sees exactly what the database enforced.
Returns: string or null
${[itemprop="price"]}.first().value()
${[itemprop="url"]}.first().value() // href for <a> elements
${[itemprop="image"]}.first().value() // src for <img> elements
${[itemprop="pubdate"]}.first().value() // datetime for <time> elements
.attr(name)
Returns the value of the named attribute, or null if the attribute is absent.
Returns: string or null
${a.external}.first().attr("href")
${img.hero}.first().attr("alt")
${div.card}.first().attr("data-id")
.path()
Returns the source document path of the element as a String, or null for constructed elements. Elements retain their source path through sub-selections and list operations.
Returns: string or null
(${h1} from "/team/benji.html").first().path() // "/team/benji.html"
(new div { }).path() // null
.document()
Returns the root element of the element's source document, or null for constructed elements. Enables navigating from a selected element back to its full document context.
Returns: element or null
(${h1} from "/team/benji.html").first().document() // root <html> element
(new div { }).document() // null
.selector()
Generates a CSS selector string that uniquely identifies the element within its document. Uses #id if the element has an id attribute, otherwise builds a tag:nth-child(n) path from the nearest ancestor with an id.
Returns: string or null
${h1}.first().selector() // "#main > h1:nth-child(1)"
${#hero}.first().selector() // "#hero"
(new div#panel { }).selector() // "#panel"
(new span { }).selector() // "span"
.microdata()
Extracts HTML Microdata from an element with itemscope into a structured Map. Properties come from descendant itemprop attributes. @id is automatically constructed from the element's source path and id attribute. Returns null if the element has no itemscope.
Returns: map or null
${[itemscope][itemtype*="Product"]}.first().microdata()
// → { "@type": "Product", "name": "Widget", "price": "29.99", "@id": "/products/widget.html#widget" }
When called on a List of elements, maps each element to its microdata:
${[itemscope]}.microdata()
// → [{ "@type": "Product", ... }, { "@type": "Product", ... }]
.clone()
Creates an independent constructed copy of the element. The clone is a ConstructedElement (mutable) and loses its source path. Works on both queried and constructed elements.
Returns: constructed element
${div.product}.first().clone() // queried element → constructed copy
(new div.card { text: "hi" }).clone() // constructed → independent copy
${[itemtype*="Product"]}.map(e => e.clone()) // clone each element in a list
.children()
Returns the direct child elements of the element as a List. Text nodes are excluded — only element nodes are returned. This walks the tree directly without using selector machinery, so it works on any element regardless of the template inert boundary.
Returns: list
${ul}.first().children() // [<li>…</li>, <li>…</li>, …]
${ul}.first().children().count() // 3
${div}.first().children().first().text()
.parent()
Returns the element's parent element — the inverse of .children(). Returns null when there is no parent element: at the top of the element tree (nothing sits above the topmost element), and on a constructed element that is itself the root of its own tree.
Upward traversal also works inside a constructed tree. A child obtained from a constructed element's .children() walks back up to its parent, and .parent() chains all the way to the constructed root. The link is live — reading a parent's attribute through a child's .parent() reflects edits made to that parent — and a child handle keeps the whole tree alive, so the traversal works even when the constructed root was only a transient value.
Returns: element or null
${li}.first().parent() // the enclosing <ul> element
${li}.first().parent().parent() // chains upward
${html}.first().parent() // null — top of the tree
(new div { }).parent() // null — constructed root
let d = new div#outer { new p { new span { } } };
d.children().first().parent().attr("id") // "outer"
d.children().first().children().first().parent().parent().attr("id") // "outer" — chains up
(new div#outer { new p { } }).children().first().parent().attr("id") // "outer" — even from a transient root
.content()
For <template> elements, returns the template's inner content as a queryable List of elements. The content is parsed into a fresh document fragment, so selectors and sub-selects work normally on the returned elements — bypassing the inert boundary that prevents selectors from descending into <template>.
Returns null for non-template elements.
Returns: list or null
${template#cart-row}.first().content()
// → [<tr>…</tr>]
${template}.first().content().${ [itemprop="price"] }.first().value()
// → "29.99"
${div}.first().content()
// → null (not a template)
.getHTML()
Returns the element's inner HTML — the serialized markup of its children, without the element's own opening/closing tags.
Returns: string
new div { new p { text: "hello" } }.getHTML()
// "<p>hello</p>"
new span {}.getHTML()
// ""
.innerhtml()
Returns the element's inner HTML. Behaves the same as .getHTML() above.
Returns: string
let el = new div { new p { text: "hello" } };
el.innerhtml().contains("hello")
// true
Sub-select: el.${ selector }
Runs a CSS selector against an element's subtree in-memory. Unlike top-level ${...} which queries stored documents, sub-select operates on already-materialized elements.
${section}.first().${ h2 } // all h2 elements within the first section
On a List, the selector runs against each element's subtree and results are concatenated into a flat list:
${[itemtype*="Product"]}.${ [itemprop="name"] }
// Equivalent to:
${[itemtype*="Product"]}.map(el => el.${ [itemprop="name"] }).flatten()
Standard CSS combinators work relative to the element root:
product.${ > [itemprop="name"] } // direct children only
product.${ h1 + p } // adjacent sibling among descendants
Setting data (constructed elements only)
Setter methods are only available on constructed elements. They follow an arity-based get/set convention: the same method name with no arguments reads and with arguments writes.
Each setter returns the modified element, so calls can be chained.
.text(expr)
Replaces the text content of the element with the result of expr.
Returns: modified element
new p.text("Hello, world")
new h1.text(${[itemprop="name"]}.first().value())
.value(expr)
Sets the microdata value of the element. Follows the same WHATWG attribute rules as .value() for reading — the appropriate attribute (href, src, data, content, value, datetime, or text content) is set based on the element tag.
Returns: modified element
new a[itemprop="url"].value("https://example.com")
new meta[itemprop="description"].value("A brief summary")
new time[itemprop="pubdate"].value("2026-03-10")
.attr(name, expr)
Sets the named attribute to the result of expr.
Returns: modified element
new div.attr("id", "main")
new a.attr("href", ${[itemprop="url"]}.first().value())
new img.attr("alt", ${[itemprop="name"]}.first().text())
Construction syntax summary
new tag.class#id[attr="literal"][attr=expression][boolean-attr] { children }
tag— required element tag name.class— shorthand forclass="..."#id— shorthand forid="..."[attr="literal"]— attribute with a string literal value[attr=expression]— attribute with a Sessel expression as value[boolean-attr]— boolean attribute (present, no value){ children }— inline child content (text or nested elements)
new p { text: "Hello" }
new a.button[href="/about"] { text: "About us" }
new input[type="checkbox"][checked] {}
new div#main.card[data-count=${.item}.count()] {}
See Constructing HTML for a full tutorial and Syntax for the complete grammar.
Mutation methods (constructed elements only)
These methods modify the element tree and return the modified element for chaining.
.append(child)
Appends the given child as the last child of the element.
Returns: modified element
new ul {}.append(new li { text: "Item" })
.prepend(child)
Inserts the given child as the first child of the element.
Returns: modified element
let el = new ul { new li { text: "b" } };
let el2 = el.prepend(new li { text: "a" });
el2.children().first().text()
// "a"
.setHTML(html)
Replaces the element's children with the parsed content of the given HTML string.
Returns: modified element
let el = new div { text: "old" };
el.setHTML("<b>new</b>");
el.getHTML()
// "<b>new</b>"
.empty()
Removes all children from the element.
Returns: modified element
let el = new div { text: "hello", new p { text: "world" } };
let el2 = el.empty();
el2.children().count()
// 0
.remove()
Removes the element from its parent. Returns null.
Returns: null
let el = new div { new p { text: "Hello" } };
el.${ p }.first().remove()
.replaceWith(replacement)
Replaces the element with the given replacement in its parent's child list. Returns the replacement element.
Returns: element
let el = new div { new p { text: "old" } };
el.${ p }.first().replaceWith(new span { text: "new" })
.insertBefore(referenceChild)
Called on the new element being inserted, not on the parent: newChild.insertBefore(referenceChild) inserts the receiver into referenceChild's parent, immediately before it. Returns the receiver (the inserted element).
Returns: element (the receiver)
let el = new ul { new li { text: "Second" } };
let newLi = new li { text: "First" };
newLi.insertBefore(el.${ li }.first())
See also
- List — element lists from selectors
- Constructing HTML — full tutorial for building elements
- Syntax — complete grammar including construction syntax
- Types — overview of all Sessel types and their methods