Appearance
DOM Factory
Helpers for creating DOM nodes — elements, text nodes, fragments, and parsed HTML — in single expressions. Namespaced under dom to avoid collisions with generic names.
When to use
Use these helpers when you need to create DOM elements in a single expression with multiple attributes, classes, or event listeners and no template library. They keep element creation compact in utility code and tests.
The pattern
Basic element with attributes
Create a DOM element with properties set in a single expression — dom.element() takes a tag name and an options object, returning a fully configured element ready to insert:
javascript
const heading = dom.element("h1", {
id: "title",
textContent: "Hello, world",
});Element with event listener
Inline event handlers work because DOM elements accept onclick and similar properties through plain assignment:
javascript
const button = dom.element("button", {
textContent: "Save",
onclick() {
save();
},
});Composing a tree
Nest dom.element() calls using childNodes to build a tree in a single expression. Strings in the array become text nodes automatically — append() handles that natively:
javascript
const card = dom.element("div", {
className: "card",
childNodes: [
dom.element("h2", { textContent: name }),
dom.element("p", { textContent: bio }),
dom.element("a", { href: url, textContent: "Profile" }),
" · ",
dom.element("a", { href: repo, textContent: "Source" }),
],
});
document.body.append(card);Fragments
dom.fragment() groups multiple nodes without a wrapper element:
javascript
const links = dom.fragment(
dom.element("a", { href: url, textContent: "Profile" }),
" · ",
dom.element("a", { href: repo, textContent: "Source" }),
);
container.append(links);Setting dataset and style
dataset, style, and childNodes work directly in the options object — the factory handles them specially instead of assigning them as properties:
javascript
const badge = dom.element("span", {
className: "badge",
textContent: count.toString(),
dataset: { status: "active" },
style: { color: "green" },
});Parsing HTML strings
dom.html() parses an HTML string into a DocumentFragment, working both as a regular function call and as a tagged template literal:
javascript
// Function call
const nav = dom.html('<nav><a href="/">Home</a></nav>');
// Tagged template literal
const greeting = dom.html`<h1>Hello, ${name}</h1>`;Both return a DocumentFragment ready to insert. The tagged template form interpolates values into the markup before parsing.
Implementation
javascript
const dom = {
element(tagName, options = {}) {
const el = document.createElement(tagName);
const { dataset, style, childNodes, ...rest } = options;
Object.assign(el, rest);
if (dataset) Object.assign(el.dataset, dataset);
if (style) Object.assign(el.style, style);
if (childNodes) el.append(...childNodes);
return el;
},
text(content) {
return document.createTextNode(content);
},
fragment(...children) {
const frag = document.createDocumentFragment();
frag.append(...children);
return frag;
},
html(strings, ...values) {
const markup = strings.raw ? String.raw(strings, ...values) : strings;
const template = this.element("template", {
innerHTML: markup,
});
return template.content;
},
};Trade-offs
| Approach | Pros | Cons |
|---|---|---|
dom factory | One expression | Custom helper |
createElement | Native, no helper | Verbose, multi-step |
Template + innerHTML | Readable markup | XSS risk |
| Framework (compiled) | Full reactivity | Build step required |
The factory is best for small-scale DOM construction — utility functions, test fixtures, or lightweight prototypes. For large component trees, prefer templates or a framework.