Web Components (Part 3): Web Components with Lit

In part two of this series, we learned how to use the browser’s native Web Component APIs. In this third part, we’ll take a look at the Lit library that we use at Puzzle ITC to build web applications, as well as component libraries and ways to set up your own Lit projects.

What is Lit?

Google launched the Polymer project in November 2013. Polymer provided polyfills for custom elements, shadow DOM, and CSS custom properties. All of these features were not supported by browsers at the time. Today, all major browsers support these features, rendering Polymer’s polyfills obsolete.
Some other key features of Polymer were its use of the HTML Import Specification and two-way data binding. The HTML Import Specification has since been removed from the Web platform. Two-way data binding, on the other hand, is very nice for small projects, but tends to make things harder to understand in more complex scenarios. As a result, two-way data binding has gone out of fashion in recent years and is generally replaced by unidirectional data flows and fine grained reactivity.

The Polymer team decided to stop maintaining Polymer and replace it with Lit, which is a direct successor. Lit has many of the same goals, but the team has applied the lessons learned from developing Polymer. With the release of Lit 2.0, the previously independent libraries lit-html and LitElement were bundled into a single package.

At its core, the Lit library simplifies Web Component development by providing reactivity, a declarative template system, scoped styles, and other features typically required to build Web Components. The lightweight library (~5 KB minified and compressed) keeps the bundle size of your application small. Lit components are native Web Components, so they work anywhere you use HTML and even with the frontend framework of your choice. It’s also possible to mix Web Components developed with any Web Component library of any version (or no library at all) on the same page.

Project Setups

As usual, there are several ways to set up a Lit project, depending on its nature. For component libraries and design systems to be used by other projects, you could use the official TypeScript starter kit or JavaScript starter kit provided by the Lit team. The main advantage of using TypeScript is the ability to use decorators. They are one of the key Lit features that allow developers to write clean, readable code when implementing Web Components with Lit. You’ll need to add an extra build step if you want to use decorators with JavaScript. However, this won’t be necessary once the decorators proposal is adopted and supported by browsers. One of the nice things about these starter kits is that they do not use any build steps for the Web Components (except for compiling TypeScript, of course). This makes the projects very light and fast. It’s also generally recommended not to bundle, minify, or optimize your component library, but to simply publish the modules in ES2021 standard syntax. This is especially true for a Lit component library, since bundling would include the Lit library itself. This could introduce Lit (and other packages) multiple times into a user’s application, and there would be no way for npm to deduplicate the packages.

The starter kits also show how to create nice lightweight documentation using the static site generator Eleventy. Although in our projects we usually use Storybook, for a more in-depth and interactive documentation. We’ll take a closer look at one of our Web Component libraries in a later part of this series.

Create a simple component library

First, clone the starter kit locally and install all dependencies:

git clone https://github.com/lit/lit-element-starter-ts.git greetings
cd greetings
npm install

Then, create a new component src/my-greeting.ts with the following contents that will greet the user with a custom name or – if no name is given – just greets the whole world.

import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators.js';

export class MyGreeting extends LitElement {

    name = 'World';

    override render() {
        return html`<h1>${this.sayHello(this.name)}!</h1>`;

    sayHello(name: string): string {
        return `Hello, ${name}!`;

declare global {
    interface HTMLElementTagNameMap {
        'my-greeting': MyGreeting;

We will also need to change the two properties main and module in the package.json file to match the new component and give the library a custom name:

    "name": "@example/greetings",
    // other properties omitted
    "main": "my-greeting.js",
    "module": "my-greeting.js",

This is necessary because the application we are going to scaffold in the next chapter also names its Lit component my-element.ts, which would lead to a conflict. Note that we are referencing the generated JavaScript file, not the TypeScript file we created earlier!

Now we have to build and link the project to create a local package of our Web Component library to use it later:

npm run build
npm link

But first we need to set up the application.

Setup a Lit Application with Vite

For applications we usually just use the Lit template from Vite. To initialize the project, open a terminal and issue the following command:

npm create vite@latest lit-application -- --template lit-ts

Scaffolding project in ~/projects/lit-application...

Done. Now run:

  cd lit-application
  npm install
  npm run dev

After installing the dependencies and running the application, open a browser and navigate to The built application will greet you with a welcome screen. The button increments a counter when clicked.

Adding our component library to the application

In your application directory, link to the Web Component library we created earlier.

npm link @example/greetings

Then open my-element.ts and import the library:

import "@example/greetings";

You can then use the component in the HTML template:

return html`
    <my-greeting name="Web Components"></my-greeting>
    // ommited rest of the html template for briefty

If you run your application now with npm run dev, it should look like the following screenshot.


Congratulations. You have just laid the foundation for your future Web Component libraries with Lit and your Lit applications. But you could add the Web Component from the component library to any other application that uses e.g. Angular or React as its framework.

Building the application

When we initialized the application using Vite’s Lit template, a build configuration was created for us. You can build the application, without any further configuration:

$ npm run build

> lit-application@0.0.0 build
> tsc && vite build

vite v4.5.0 building for production...
✓ 44 modules transformed.
dist/index.html                  0.50 kB │ gzip:  0.31 kB
dist/assets/lit-c8dae599.svg     0.64 kB │ gzip:  0.38 kB
dist/assets/index-8b380820.css   0.56 kB │ gzip:  0.37 kB
dist/assets/index-b6f9725b.js   52.30 kB │ gzip: 11.54 kB
✓ built in 587ms

As you can see, the final bundle size is only 11kB (gzipped), which is quite small.


The Lit library benefits from years of experience gained during the development of its predecessor Polymer. It simplifies the development of Web Components by reducing the amount of boilerplate you have to write and provides some additional features to build fast, lightweight Web Components and applications.

Setting up basic starters for a Web Component Library and an application using Lit is quite easy given the provided starter kits or projects like Vite, that also support Lit. Both projects shown in this article are just examples. You should document and unit test your components as well as your applications and tailor the setup to your needs or add the tools you usually use at your company. Maybe you want to use Storybook instead of Eleventy to document your library or Tailwind CSS for styling?

Coming Up

While setting up the projects, almost no explanations on how to use the Lit library were given. In the next article, we will dive deeper and compare the concepts of Lit with the popular frontend framework Angular.

All articles of the series:


Kommentare sind geschlossen.