The Tagged Template syntax for Virtual DOM. Only browser-compatible syntax.
npm install htm

htm is JSX-like syntax in plain JavaScript - no transpiler necessary.
Develop with React/Preact directly in the browser, then compile htm away for production.
It uses standard JavaScript [Tagged Templates] and works in [all modern browsers].
htm by the numbers:š£ < 600 bytes when used directly in the browser
āļø < 500 bytes when used with Preact _(thanks gzip š)_
š„ < 450 byte htm/mini version
š 0 bytes if compiled using [babel-plugin-htm]
The syntax you write when using HTM is as close as possible to JSX:
- Spread props: Here's some ergonomic features you get for free that aren't present in JSX: - No transpiler necessary via npm: `` hotlinking from unpkg: _(no build tool needed!)_ ` ` If you're using Preact or React, we've included off-the-shelf bindings to make your life easier. ` Similarly, for React: ` Since htm Here's an example h() ` To use our custom h() ` const html = htm.bind(h); Now we have an html() Here's the whole thing for clarity: ` function h(type, props, ...children) { const html = htm.bind(h); console.log( html If the template has multiple element at the root level The default build of * Change your Curious to see what it all looks like? Here's a working app! It's a single HTML file, and there's no build or tooling. You can edit it with nano. ā”ļø Try this on CodeSandbox ā¶ How nifty is that? Notice there's only one import - here we're using the prebuilt Preact integration since it's easier to import and a bit smaller. The same example works fine without the prebuilt version, just using two imports: const html = htm.bind(h); render(html Since Generate HTML using [vhtml]: const html = htm.bind(vhtml); console.log( html Webpack configuration via [jsxobj]: (details here) _(never do this)_ const html = htm.bind(jsxobj); console.log(html - Canadian Holidays: A full app using HTM and Server-Side Rendering The original goal for This meant giving up JSX, and the closest alternative was [Tagged Templates]. So, I wrote this library to patch up the differences between the two as much as possible. The technique turns out to be framework-agnostic, so it should work great with any library or renderer that works with JSX. [Tagged Templates]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates instead of
- Self-closing tags:
- Components: <${Foo}> instead of _(where Foo is a component reference)_
- Boolean attributes: Improvements over JSX
htm actually takes the JSX-style syntax a couple steps further!
- HTML's optional quotes:
- Component end-tags: <${Footer}>footer content/>
- Syntax highlighting and language support via the [lit-html VSCode extension] and [vim-jsx-pretty plugin].
- Multiple root element (fragments):
- Support for HTML-style comments: Installation
htm is published to npm, and accessible via the unpkg.com CDN:js`
npm i htmjs`
import htm from 'https://unpkg.com/htm?module'
const html = htm.bind(React.createElement);js`
// just want htm + preact in a single file? there's a highly-optimized version of that:
import { html, render } from 'https://unpkg.com/htm/preact/standalone.module.js'Usage
They also have the added benefit of sharing a template cache across all modules.jsHello!
import { render } from 'preact';
import { html } from 'htm/preact';
render(html, document.body);`jsHello!
import ReactDOM from 'react-dom';
import { html } from 'htm/react';
ReactDOM.render(html, document.body);`$3
is a generic library, we need to tell it what to "compile" our templates to.htm
You can bind to any function of the form h(type, props, ...children) _([hyperscript])_.htm
This function can return anything - never looks at the return value. function that returns tree nodes:js`
function h(type, props, ...children) {
return { type, props, children };
} function, we need to create our own html tag function by binding htm to our h() function:js
import htm from 'htm';
` template tag that can be used to produce objects in the format we created above.js
import htm from 'htm';
return { type, props, children };
}Hello world!
);`
// {
// type: 'h1',
// props: { id: 'hello' },
// children: ['Hello world!']
// }h
the output is an array of results:`js
console.log(html
Hello
World!);`
// [
// {
// type: 'h1',
// props: { id: 'hello' },
// children: ['Hello']
// },
// {
// type: 'div',
// props: { class: 'world' },
// children: ['world!']
// }
// ]htm$3
caches template strings, which means that it can return the same Javascript object at multiple points in the tree. If you don't want this behaviour, you have three options:h function to copy nodes when needed.this[0] = 3;
* Add the code at the beginning of your h function, which disables caching of created elements.htm/mini
* Use , which disables caching by default.`Example
html`
`js<${App} page="All" />
import { h, Component, render } from 'preact';
import htm from 'htm';, document.body);`htmOther Uses
is designed to meet the same need as JSX, you can use it anywhere you'd use JSX.`js
import htm from 'htm';
import vhtml from 'vhtml';Hello world!
);`
// 'Hello world!
'`js
import htm from 'htm';
import jsxobj from 'jsxobj';
);`
// {
// watch: true,
// mode: 'production',
// entry: {
// path: 'src/index.js'
// }
// }htmDemos & Examples
- HTM SSR Example: Shows how to do SSR with HTM
- HTM + Preact SSR Demo
- HTM + vhtml SSR DemoProject Status
was to create a wrapper around Preact that felt natural for use untranspiled in the browser. I wanted to use Virtual DOM, but I wanted to eschew build tooling and use ES Modules directly.htm` is stable, fast, well-tested and ready for production use.
[lit-html]: https://github.com/Polymer/lit-html
[babel-plugin-htm]: https://github.com/developit/htm/tree/master/packages/babel-plugin-htm
[lit-html VSCode extension]: https://marketplace.visualstudio.com/items?itemName=bierner.lit-html
[vim-jsx-pretty plugin]: https://github.com/MaxMEllon/vim-jsx-pretty
[vhtml]: https://github.com/developit/vhtml
[jsxobj]: https://github.com/developit/jsxobj
[hyperscript]: https://github.com/hyperhype/hyperscript
[all modern browsers]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Browser_compatibility