A lightweight library for effortlessly creating HTML and SVG elements in JavaScript.
// Shoelace SlButton component
import "https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/cdn/components/button/button.js"
// Domxy library
import { domxy } from "https://domxy.js.org/domxy.js"
// Destructure elements you want to use (including Custom Elements)
const { div, form, input, label, SlButton } = domxy
// Example form
const nameForm = form({ dataController: "hello" } },
div({ class: "form-group" },
label({ for: "name" }, "Name"),
input({
dataset: {
helloTarget: "name"
},
id: "name",
name: "name",
placeholder: "enter a name",
type: "text"
}),
),
SlButton({ dataset: { action: "click->hello#greet" } }, "Submit"),
)
// Append to the DOM
document.body.append(nameForm)
<form data-controller="hello">
<div class="form-group">
<label for="name">Name</label>
<input data-hello-target="name" id="name" name="name" placeholder="enter a name" type="text">
</div>
<sl-button data-action="click->hello#greet">Submit</sl-button>
</form>
- ✨ Create HTML and SVG elements expressively
- ☕ Pure JavaScript, no special syntax to learn
- 🤙 Every element is a function call
- 🪪 Optionally pass attributes and properties, including
data
andaria
- ⚡ Supports Custom Elements with Pascal-cased names
- 🚫 No need for a build tool
- 📦 Standard ES Module
domxy is a JavaScript Proxy object that generates HTML and SVG DOM elements using an HTML-like syntax in pure JavaScript.
You must destructure the elements from the domxy object before using:
const { div, form, input, label, SlButton } = domxy
Custom Element instances can be created using Pascal case naming:
form(
SlInput({ variant: "danger" }), // sl-input
SlButton({ type: "submit" }, "Submit") // sl-button
)
Data attributes and ARIA attributes can be assigned using Camel case names or the dataset
or aria
property:
span({
aria: { labelledby: "tac", },
ariaChecked: true,
dataset: { test: true },
role: "checkbox",
tabindex: 0
}),
span({ id: "tac" }, "I agree to the Terms and Conditions.")`)
<span aria-checked="false" aria-labelledby="tac" data-test="true" role="checkbox" tabindex="0"></span>
<span id="tac">I agree to the Terms and Conditions.</span>
Boolean properties are set using true
or false
:
details({ open: true },
summary("Details"),
p({ contenteditable: true }, "Something small enough to escape casual notice.")
);
ARIA attributes can be assigned using Camel case names or the aria
property:
span({
aria: {
labelledby: "tac",
},
ariaChecked: true,
role: "checkbox",
tabindex: 0
}),
span({ id: "tac" }, "I agree to the Terms and Conditions.")
<span
aria-checked="false"
aria-labelledby="tac"
role="checkbox"
tabindex="0"
></span>
<span id="tac">I agree to the Terms and Conditions.</span>
Create SVG elements just like any other HTML element:
button({ type: "button" },
svg({ ariaHidden: true, class: "icon", viewBox: "0 0 20 20" },
path({
d: "M17,15.98059V17a1,1,0,0,1-1,1H4a1,1,0,0,1-1-1V15.98059a.9998.9998,0,0,1,.37531-.78082l2.556-2.0448A4.00431,4.00431,0,0,0,9.2998,15h1.4004a4.00431,4.00431,0,0,0,3.36853-1.845l2.556,2.0448A.9998.9998,0,0,1,17,15.98059ZM7.47211,11.81226A2,2,0,0,0,9.29974,13h1.40052a2,2,0,0,0,1.82763-1.18774L13.65527,9.2757A4.00024,4.00024,0,0,0,14,7.65112V6a3.97577,3.97577,0,0,0-4-4A4.1928,4.1928,0,0,0,6,6.17206V7.65112A4.00024,4.00024,0,0,0,6.34473,9.2757Z",
})
),
"Acccount"
)
Create a DocumentFragment using the fragment
function:
fragment(
h1("Title"),
p("Intro paragraph.")
)
#document-fragment
<h1>Title</h1>
<p>Intro paragraph.</p>
In addition to String
, Number
and Boolean
types, attributes can accept Date
, Array
and Object
types as values by calling JSON.stringify() on them:
div({ dataModel: { type: "user", active: false } })
<div data-model="{"type":"user","active":false}"></div>
While not a domxy feature, if used inside of a JavaScript class, you can take advantage of inline property assignment to "define and assign" elements as references for later use:
class HsCard extends BitElement {
static properties = {
copy: { type: String, required: true },
image: { type: String },
link: { type: URL },
title: { type: String, required: true },
}
constructor() {
super();
this.shadowRoot.append(
this.imageEl = img({ alt: "" }),
this.titleEl = h2(),
this.copyEl = p("Default copy ",
this.linkEl = a("Card link")
),
)
}
update() {
this.copyEl.textContent = this.copy
this.imageEl.src = this.image
this.linkEl.href = this.link.href
this.titleEl.textContent = this.title
}
}
Whether you need to or enjoy working with DOM elements directly in JavaScript, you know how verbose creating and forming them into even a modest tree can get.
domxy makes working with DOM nodes easy, expressive and powerful.
Import domxy as an ES module:
import { domxy } from "https://domxy.js.org/domxy.js"
const { h1, main } = domxy
document.body.append(
main(
h1("Hello, domxy.")
)
)
- Run tests.html in a web browser
- Open the Developer Tools and select the Console tab
- All tests passed! or the error and line number will display in the console
domxy was created by Joe Dakroub and is released under the Unlicense.
Detailed changes for each release are documented in the release notes.
If you find domxy useful, please consider a small donation; definitely not required. Thank you! 🙏