Skip to content

Manjula Dube

Lit-html v/s Libraries like React, Preact.

3 min read

Lit-html is a small, lightweight templating library. Lit-html uses JavaScript template strings to create expressive, dynamic templates. Alongside of the lit-html library, Polymer has also released a lightweight base Class called lit-element. Using lit-element, we can easily create Web Components with higher level APIs built on the Web Component primitives we discussed in introduction to Web Components.


In this post, we are going to create a counter component using lit-html and lit-element. Here is a sample of what our counter looks like.

Let’s start with the minimal code needed to create our Web Component using the base class lit-element.

To create our Web Component, we import the LitElement class from the lit-element package lit-element. Extending the LitElement class will allow us to use the built in functionality to make it easy to construct our component. With lit-element we implement a method render(). The render method will be executed whenever a property on our component changes.

The render() method expects a template to be returned. To create a lit-template we use the html function to create a tagged template. The html function allows us to use JavaScript template strings to attach additional behaviour that lit-html provides. In this example so far we only render a static value. Next, we need to create our template.

Lit-html templates and event listeners

We need to add the template for our counter component. Lit-html also automatically creates our template with a Shadow DOM instance, so we get CSS encapsulation. On our counter component, we also need to create some event handlers for the click events on our buttons. Let’s go ahead and take a look at the code.

To create an event listener in lit-html templates, we can declaratively bind to elements. For example to bind to a click event we use the @ symbol with click. In our the template we are going to add one click event for each button.

When binding to an event, you can run any JavaScript expression so you can call a method in the class or in our case just this.value--. Now if we try to run our code, nothing happens. We still need to add some additional information for our value property.

Properties, Attributes and Decorators

We need to give lit-element some additional metadata to tell it what properties should trigger a re-render on the component. To do this, we will add a static list of properties for lit-html to track.

The static property list allows lit-html to track which properties to trigger re-renders as well as what properties to expose to consumers of our components.

The alternative syntax @property, is a decorator provided by lit-element. The @propertydecorator with the field initialization syntax is a shorthand over using the static list syntax. If you are using lit-html with TypeScript you can use this shorter syntax. If using Babel you will have to enable some experimental settings.

The second behaviour of the static list describes how the corresponding attribute value should be parsed as. For example if we set the value via the HTML,

With HTML attributes the attribute value is always treated as a string. In our static property list we are explicitly telling the lit-element when it reads the string ‘5’ from the HTML it should parse it as a number type instead.

Custom Events

Just like events with vanilla custom elements, lit-element uses the same event mechanism.

In our final version of our counter component, we refactored to have a increment() and decrement() method. When the click events call these methods, they trigger the _valueChanged() method to be called which triggers our standard custom event for Custom Elements.

Now we can listen to our custom valueChange event just like any other DOM event.

Binding to other Web Components with lit-html

We have covered how to build a Web Component with lit-html and lit-element. Next we are going to cover how to use lit-html to declaratively bind and use other Web Components.

In our example, we are going to create a top-level app component that will declaratively use our counter-example component.

Now in our app template, we need to listen to the valueChange event. To do this, we bind just as we would with a click event. @valueChange=${(e) => this.log(e)}

Thanks for reading this article !!!