Skip to content

Introduction

Lift HTML is a tiny library for building HTML Web Components - components that enhance existing HTML on the page instead of rendering it on the client or hydrating it.

Lift HTML follows the HTML Web Components pattern, which means:

  • HTML is rendered on the server - Your components enhance existing HTML rather than rendering it
  • Progressive enhancement - Components add interactivity to static HTML
  • Minimal overhead - Start with as little as 150 bytes gzipped
  • Framework-agnostic - Works with any existing setup
  • Type-safe - Full TypeScript support out of the box

The core package providing the basic liftHtml function for creating web components. Perfect for simple components that don’t need reactive state management.

Bundle size: ~600 bytes gzipped

Includes the core functionality plus SolidJS integration for reactive components. Provides liftSolid function and useAttributes helper.

Bundle size: ~3.4kb gzipped (includes solid-js)

Minimal package for the most basic use cases. Provides just the essential functionality.

Bundle size: ~150 bytes gzipped

Get started with Lift HTML in just a few steps:

Terminal window
npm install @lift-html/core
import { liftHtml } from "@lift-html/core";
const MyButton = liftHtml("my-button", {
init() {
const button = this.querySelector("button");
if (!button) throw new Error("<my-button> must contain a <button>");
let count = 0;
button.onclick = () => {
count++;
button.textContent = `Clicks: ${count}`;
};
button.textContent = `Clicks: ${count}`;
},
});
<my-button>
<button disabled>Loading...</button>
</my-button>
Terminal window
npm install @lift-html/solid
import { liftSolid } from "@lift-html/solid";
import { createEffect, createSignal } from "solid-js";
const MyButton = liftSolid("my-button", {
init() {
const button = this.querySelector("button");
if (!button) throw new Error("<my-button> must contain a <button>");
const [count, setCount] = createSignal(0);
button.onclick = () => setCount(count() + 1);
createEffect(() => {
button.textContent = `Clicks: ${count()}`;
});
},
});
  • 🚀 Tiny - Start with 150 bytes, scale up as needed
  • 🔧 Framework-agnostic - Works with any existing setup
  • 🎯 Type-safe - Full TypeScript support
  • 🌐 Web standards - Uses native web APIs and standards
  • ♻️ Reactive - Optional SolidJS integration for reactive state
  • 🔥 HMR support - Hot Module Replacement out of the box

Traditional web component frameworks often focus on rendering HTML on the client side. Lift HTML takes a different approach:

  • Server-rendered HTML - Your HTML is generated on the server, providing better SEO and initial load performance
  • Progressive enhancement - Components add interactivity to existing HTML rather than replacing it
  • Better accessibility - HTML is available immediately, even before JavaScript loads
  • Simpler mental model - You write HTML, then enhance it with JavaScript

Here’s a complete example that works right now:

<my-button>
<button disabled>
Loading...
</button>
</my-button>
<script type="module">
import { liftSolid } from "https://esm.sh/@lift-html/solid";
import { createEffect, createSignal } from "https://esm.sh/solid-js";
const MyButton = liftSolid("my-button", {
init() {
const button = this.querySelector("button");
if (!button) throw new Error("<my-button> must contain a <button>");
button.disabled = false;
const [count, setCount] = createSignal(0);
button.onclick = () => setCount(count() + 1);
createEffect(() => {
button.textContent = `Clicks: ${count()}`;
});
},
});
</script>

Total code size: 3.41kb gzip