The Lit authors tried hard to use vanilla JS everywhere they could, and it shows.
We use them to make fields reactive mostly, and I love how declarative they are. But we use them sparingly. I personally don't love how some libraries try to put a lot of things into decorators that could have been standard class features, like a static field or a method.
edit: As mentioned by skrebbel, decorators are optional. Every decorator has a simple plain-JS way of doing it. Event reactive properties: https://lit.dev/docs/components/properties/#declaring-proper...
We also put a lot of effort into making all of our documentation and playground samples on lit.dev available in both JavaScript and TypeScript with decorators. There's a switch that will change everything on the site from JS to TS globally.
export class SimpleGreeting extends LitElement {
...
}
customElements.define('simple-greeting', SimpleGreeting);
I have actually wrote a few web components by hand in an environment where I didn't want any external dependencies and when that requirement was dropped I really liked how easy was to convert them to LitElement (and how much nicer it is to work with them).
I also have embraced the shadow DOM which is a default, but I think it's more trouble than it's worth. Now I use LitElement without shadow DOM and it works great as well.
- Custom HTML-like syntax
<button @click="" .disabled="" />
- Custom Javascript rules // valid JS, invalid lit
const tagName= "a";
`<${tagName} href="">Some link</${tagName}>`
- Custom rules for special functions. // classMap looks like a regular JS function, but it's not.
// Both of these will produce an error
<div class="my-widget ${classMap(dynamicClasses)} ${classMap(dynamicClasses)}">Static and dynamic</div>
<div data-class="${classMap(dynamicClasses)}">Static and dynamic</div>
- Context https://lit.dev/docs/data/context/- Experimental compiler: https://github.com/lit/lit/tree/main/packages/labs/compiler#...
Yes, Lit templates give some special meaning to attribute names with a few prefixes. No, it's not "HTML-like". It's valid HTML. Not that it matters much. You bring this up all the time but I'm not sure what the actual criticism is. Developers seem to understand the small syntax carve-out just fine.
No, there are no custom JavaScript rules. Templates have some rules. I'm not sure why they wouldn't? In general you can't make things like tag and attribute names dynamic because you can't change them in HTML. You can actually write the template you show with what we call static templates though.
`classMap()` is a template directive. It has some rules about how it's used in templates, just like other JS functions can have rules about how their used. I'm not sure what makes that not a function.
But to your main point: Lit is not like React because it's not a framework. Lit helps you make custom elements - it's an implementation detail of some web components. Everything else about those elements: how you instantiate them, style them, where they work, etc., is all defined by the HTML and DOM standards. React is a framework, and defines its own rules about how its components work.
Yes, yes I do. Because Web Components are almost 15 years now, and they still struggle with the most basic of things. How's that abandoned roadmap going? https://w3c.github.io/webcomponents-cg/2022.html
> No, there are no custom JavaScript rules. Templates have some rules.
That is "here are regular JS functions. However, you cannot use them as regular JS functions in these specific contexts". Reminds me of certain very specific rules about specific functions in specific contexts in some other framework. Can't put my finger on it.
> I'm not sure what makes that not a function.
I never said it doesn't make it a function.
> But to your main point: Lit is not like React because it's not a framework.
Yeah, React wasn't a framework either, but just a library. Everything about DOM elements that React produces, how you instantiate them, style them, where they work etc. is all defined by the HTML and DOM standards.
But then React grew in the number of features, and can no longer be called a library even though still the only thing it does is output some DOM nodes.
I guess you'll insist on Lit being "just a library" even after it adds a ton of other functionality all other frameworks already have or are moving towards.
> I'm not sure what the actual criticism is
The criticism is usual: Lit is rapidly absorbing all the features from all the other frameworks and becoming a framework itself while many of its developers and proponents can't stop shitting all over other frameworks.
Not sure why Lit showed up on the front page tonight :)
Apps are well served because they have more control about how components are used: they can import the same shared styles into every component, take are to not double-register elements, etc.
But I think there are some important standards still missing that would open things up even more in the design system and standalone components side:
- Scoped custom element registries. This moves away from a single global namespace of tag names. Seems like it's about to ship in Safari. Chrome next.
- Open styleable shadow roots. Would allow page styles to flow into shadow roots. This would make building components for use with existing stylesheets easier.
- CSS Modules. Import CSS into JS. Shipping in Chrome. About to land in Firefox.
- ARIA reference target: make idref-based reference work across shadow roots
I use it in almost all my personal websites. And when I don't use it, I end up reinventing half of it and realize I should have used it from the start. This command is in most of my projects:
curl -L https://cdn.jsdelivr.net/npm/lit-html@3/lit-html.js -o ${project}/lit-html.js
I've never felt I'm using a framework or anything that deviates from Vanilla JS and valid HTML, which is why using it hardly causes any more cognitive load than using regular string templates and JavaScript functions. Which is something that I can't say about other frontend tools.Another thing I like from Lit is that with the CDN bundle, it's straightforward to experiment and use all the features without needing a build step.
Web components are nice because they're browser-native, but they don't support reactivity, which in hindisight, is a massive oversight, issue, whatever you want to call it - it's hindered adoption.
Lit is nice because there's a very straightforward progression from web components.
There is a proposal in TC39 for native signals, which I think would make a huge dent towards library-less reactivity.
I'm also working on a proposal for native reactive templating which would more-or-less obsolete lit-html. I wrote about the idea some on my blog:
- The time is right for a DOM templating API https://justinfagnani.com/2025/06/26/the-time-is-right-for-a...
- What should a native DOM templating API look like? https://justinfagnani.com/2025/06/30/what-should-a-dom-templ...
HTTP/3, import maps, and HTML preloads can make unbundled app deployment almost reasonable in some cases. You'd still miss out on minification and better compression form a bundle. Shared compression dictionaries will make this better though.
In comparison, Angular is a monster, and React is designed for the old browser capabilities, and is now staying around by inertia, not by inherent quality.
Really love the abstraction that makes web components easy to use.
zacian•1h ago