Getting Started
Learn the basics of Just DOM
Prefer a full Vite project with jd.config already wired? Run npm create just-dom@latest — see Installation and App setup for prompts and flags (--js, --plugins=…, --css=…, --pnpm, --yes, …).
Import
Just DOM supports multiple import methods for maximum flexibility:
// Default import — the DOM object with all tag functions
import DOM from "just-dom";
// Named imports — individual utility functions
import { createRef, createRoot, createElFromHTMLString } from "just-dom";
// Combined
import DOM, { createRef, createRoot } from "just-dom";Optional: one configured jd for the whole app
For anything beyond the default DOM export—especially plugins—it helps to centralize setup in a single module (often jd.config.ts) and import jd from there in your entry file and components. That pattern is documented in App setup (jd.config).
To bootstrap a new Vite + TypeScript project with jd.config.ts already in place, use create-just-dom (npm create just-dom@latest).
Creating Elements
Every HTML, SVG, and MathML tag is available as a method on the DOM object. Each method accepts an optional props object and optional children.
import DOM from "just-dom";
// Simple element with text content
const heading = DOM.h1({}, "Hello, world!");
// Element with attributes
const link = DOM.a({ href: "https://example.com", target: "_blank" }, "Click me");
// Element with children
const list = DOM.ul({ className: "menu" }, [
DOM.li({}, "Home"),
DOM.li({}, "About"),
DOM.li({}, "Contact"),
]);Attributes, Styles, and Events
All element configuration goes through a single props object:
const button = DOM.button(
{
className: "btn btn-primary",
id: "submit-btn",
disabled: false,
// Inline styles as an object
style: {
backgroundColor: "blue",
color: "white",
padding: "8px 16px",
borderRadius: "4px",
},
// Event listeners with "on" prefix
onclick: () => alert("Clicked!"),
onmouseenter: () => console.log("Hovered"),
// Data attributes
"data-action": "submit",
},
"Submit"
);Styles
Pass styles as a Partial<CSSStyleDeclaration> object — the same properties you would use with element.style:
const box = DOM.div({
style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "200px",
height: "200px",
backgroundColor: "#f0f0f0",
},
}, "Centered content");Events
Prefix any DOM event with on to attach a listener:
const input = DOM.input({
type: "text",
placeholder: "Type something...",
oninput: (e) => console.log(e.target.value),
onfocus: () => console.log("Focused"),
onblur: () => console.log("Blurred"),
});Data Attributes
Data attributes can be set using data-* syntax:
const card = DOM.div({
"data-id": "123",
"data-category": "featured",
}, "Card content");Mounting to the DOM
Use createRoot to mount your element tree into a container:
import DOM, { createRoot } from "just-dom";
const app = DOM.div({ className: "app" }, [
DOM.header({}, [
DOM.h1({}, "My App"),
]),
DOM.main({}, [
DOM.p({}, "Welcome to my application built with Just DOM."),
]),
]);
// Mount by ID
createRoot("app", app);
// Or by element reference
createRoot(document.body, app);Using Refs
Refs let you keep a reference to a DOM element for later use:
import DOM, { createRef, createRoot } from "just-dom";
const inputRef = createRef<"input">();
const form = DOM.div({}, [
DOM.input({
ref: inputRef,
type: "text",
placeholder: "Enter your name",
}),
DOM.button(
{ onclick: () => console.log(inputRef.current?.value) },
"Get Value"
),
]);
createRoot("app", form);Fragments
Group elements without adding an extra wrapper node to the DOM:
import DOM from "just-dom";
const fragment = DOM.fragment([
DOM.h2({}, "Title"),
DOM.p({}, "Paragraph one"),
DOM.p({}, "Paragraph two"),
]);
document.body.appendChild(fragment);Full Example
Here is a complete example that puts everything together:
import DOM, { createRef, createRoot } from "just-dom";
const inputRef = createRef<"input">();
const listRef = createRef<"ul">();
const addItem = () => {
const value = inputRef.current?.value;
if (!value) return;
const item = DOM.li(
{
style: { padding: "8px", borderBottom: "1px solid #eee" },
},
value
);
listRef.current?.appendChild(item);
if (inputRef.current) inputRef.current.value = "";
};
const app = DOM.div({ className: "todo-app" }, [
DOM.h1({}, "Todo List"),
DOM.div({ style: { display: "flex", gap: "8px", marginBottom: "16px" } }, [
DOM.input({
ref: inputRef,
type: "text",
placeholder: "Add a new task...",
onkeydown: (e) => { if (e.key === "Enter") addItem(); },
}),
DOM.button({ onclick: addItem }, "Add"),
]),
DOM.ul({ ref: listRef, style: { listStyle: "none", padding: "0" } }),
]);
createRoot("app", app);