Sharing is caring!

Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.

HTM (Hyperscript Tagged Markup) npm

hyperscript tagged markup demo

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:

???? < 700 bytes when used directly in the browser

⚛️ < 500 bytes when used with Preact (thanks gzip ????)

???? 0 bytes when compiled using babel-plugin-htm

Syntax: like JSX but also lit

The syntax you write when using HTM is as close as possible to JSX:

  • Spread props: &lt;div ...${props}&gt;
  • Self-closing tags: &lt;div /&gt;
  • Components: &lt;${Foo}&gt; (where Foo is a component reference)
  • Boolean attributes: &lt;div draggable /&gt;

Improvements over JSX

htm actually takes the JSX-style syntax a couple steps further!

Here’s some ergonomic features you get for free that aren’t present in JSX:

  • No transpiler necessary
  • HTML’s optional quotes: &lt;div class=foo&gt;
  • Component end-tags: &lt;${Footer}&gt;footer content&lt;//&gt;
  • Syntax highlighting and language support via the lit-html VSCode extension.


htm is published to npm, and accessible via the unpkg.com CDN:

via npm:

npm i htm

hotlinking from unpkg: (no build tool needed!)

import htm from 'https://unpkg.com/htm?module'
const html = htm.bind(React.createElement);
// 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.mjs'


Since htm is a generic library, we need to tell it what to “compile” our templates to.

The target should be a function of the form h(type, props, ...children) (hyperscript), and can return anything.

// this is our hyperscript function. for now, it just returns a description object.
function h(type, props, ...children) {
  return { type, props, children };

To use that h() function, we need to create our own html tag function by binding htm to our h() function:

import htm from 'htm';

const html = htm.bind(h);

Now we have an html() template tag that can be used to produce objects in the format we created above.

Here’s the whole thing for clarity:

import htm from 'htm';

function h(type, props, ...children) {
  return { type, props, children };

const html = htm.bind(h);

console.log( html`<h1 id=hello>Hello world!</h1>` );
// {
//   type: 'h1',
//   props: { id: 'hello' },
//   children: ['Hello world!']
// }

Subscribe to the Newsletter

Get our latest news,tutorials,guides,tips & deals delivered to your inbox.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.