A micro HTML/SVG render
- no diffing whatsoever, it's just a faster, and smarter
innerHTML
equivalent - nodes with a
name="..."
attribute are collected once - arrays in holes are joined with a space in between
- no repeated render, per each node, when same template literal is used
- a perfect tiny companion for wickedElements or hookedElements
The key of uhtml is size and simplicity: nothing is transformed, transpiled, or mapped, you have full freedom to define layouts and enrich these later on.
import {render, html, svg} from 'uhtml';
const {render, html, svg} = require('uhtml');
// https://unpkg.com/uhtml
Anything in the template gets in as is, with the exception of arrays, joined via a space, so that classes, as well as list of elements, can get in too.
import {render, html, svg} from 'uhtml';
const {title, kind} = render(
document.body,
html`
<h1 name="title" class="${['a', 'b', 'c']}">Hello uHTML!</h1>
<p>
Welcome to this <span name="kind">old</span> adventure!
</p>
`
);
// every name in the template results into an element
title.style.textDecoration = 'underline';
kind.textContent = 'new';
Feel free to check this live counter demo to better understand how this works.
How is this any better than innerHTML
?
uhtml never pollutes, trash, or recreate, content defined via a template literal.
In case you didn't know, template literals are unique per scope, so that defining some HTML or SVG content for a specific node passed as render
argument, never replaces the content that was previously there, if the template literal is exactly the same.
Moreover, if you use innerHTML
for SVG content, that won't work the way you'd expect.
uhtml does indeed the minimum amount of processing to ensure your HTML or SVG content is injected once, and only if the template literal is different from the previous one.
Can I use nested html
or svg
in the template ?
The TL;DR answer is no, 'cause those utilities are there to define the kind of content you want for that specific node, instrumenting few DOM APIs to provide such content within fragments.
This boils down to the inability, or the anti-pattern, to have lists created within a template, unless you take over such list, through a named element, in a way that allows you to update, replace, or drop, such list later on.
The domdiff module, in such cases, might be a solution, otherwise you are in charge of handling inner lists changes.
Should I hydrate each content manually ?
The name
attribute simplifies the retrieval of elements within the template.
From that time on, you are in charge of populating, or manipulating, anything you like, and per each named node.
Please note that a query such as [name]
will return anything found in the template, so that name clashing is inevitable, if you use the same attribute within other elements/components defined in your template.