A couple blog posts detailing the rationale for an using tagged template literals:
- Templating in JavaScript, From Zero Dependencies on Up
- JSX-Like Syntax for Tagged Template Literals in JavaScript
- Static Site Templating: Switching from React & JSX to JavaScript & Template Literals
Copy/paste the contents of html.js
into your own codebase.
Or, install it in your project (this isn't published on NPM, but you can install directly from GitHub or pull it in from a service like jsdeliver):
- Node:
npm i jimniels/html
- Browser:
import html from "https://cdn.jsdelivr.net/gh/jimniels/html@0.2.0/html.js"
Sometimes you just don’t need a bespoke templating languages with its quirks and dependneices. Just Use JavaScript™️.
Example trade-offs of using template literals over JSX:
- No more trying to remember which custom attributes require their own spcial syntax. Just use the platform standard names. For example:
class=""
instead ofclassName=""
for=""
instead ofhtmlFor=""
style="font-weight: 600"
isntead ofstyle={{ fontWeight: 600 }}
- Use standard SVG attributes too without worry! e.g.
xlink:href
instead ofxlinkHref
- Render more than just HTML without a problem: SVG, JSON, whatever! It’s all just text. No need to try and do special fragment workarounds.
- No
dangerouslySetInnerHTML
(in a sense, everything in template literals isdangerouslySetInnerHTML
, you just escape the things you know are unsafe). - Do templating in the script tags in your HTML, e.g.
<script>var t = "${myVar}";</script>
Everything in template literals is an expression. The tagged html
template literal will handle coercing JSX-like expressions into the correct strings for you.
Render a string or number:
const props = { title: "Hello World" };
const Component = (props) => html`
<h1>${props.title}</h1>
`;
Component(props);
// -> "<h1>Hello World</h1>"
Note: line breaks and indents will appear in multi-line strings. There are libraries to help with this if you need them.
“Components” are merely functions that take arguments and return strings:
const H1 = ({ text }) => html`
<h1>${text}</h1>
`;
const H2 = ({ text }) => html`
<h2>${text}</h2>
`;
const out = `<!doctype html>
<html>
<body>
${H1({ text: "Hello" })}
${H2({ text: "World" })}
</body>
</html>
`;
// -> "<!doctype html><html><body><h1>Hello</h1><h2>World</h2></body></html>"
Use conditionals and arrays just like in JSX too!
const props = {
activePath: "/about/",
navItems: [
{ path: "/", title: "Home" },
{ path: "/about/", title: "About" },
{ path: "/tags/", title: "Tags" }
]
};
const Navigation = ({ activePath, navItems }) => html`
<ul class="navigation">
${navItems.map(({ path, title }) => html`
<li>
<a
class="${activePath === path && 'active'}"
href="${path}">
${title}
</a>
</li>
`)}
</ul>
`;
Navigation(props);
// -> <ul class="navigation"><li><a class="" href="/">Home</a></li>...</ul>
And make sure you get syntax highlighting for the HTML embedded in template literals.