Get the top HN stories in your inbox every day.
Muromec
compacct27
Integrating these web components into our React codebase has been pretty awful--more of a web components thing than a Lit thing, IMO. We have "scoped styles", except for certain important things like font sizes, so tons of little regressions everywhere when we swap in the web component in place of the old React one. DX-wise, we lost a lot, too. I assume the tooling will get better, or that we'll figure it out more, but it's mostly been a drag
Muromec
Are you migrating from react to something else? I see the appeal of web components as a middle ground for base library when different frameworks coexist (temporarily or not), but everyone is so hellbent on monoculture this days that I don't see the point really.
kubb
Shadow DOM is optional in Lit - you can just disable it on a per-component basis.
jazzypants
It should not be the default. This is almost certainly Lit's biggest flaw.
I am currently working on a web components framework, and I scrapped everything halfway through after I realized that you very rarely want that much encapsulation. Now, you can turn it on if you really need it, and I even made a way where you can pass references to DOM elements and stylesheets and such into each component so you can pierce the shadow veil easily. I have one demo to show it off, but I'm really having trouble imagining when someone would actually want to use it. The only time I can imagine it being useful would be building component libraries inside of large organizations.
I'm not ready to show off my framework yet, but I'm very certain that this leads to a better DX.
Muromec
>The only time I can imagine it being useful would be building component libraries inside of large organizations.
That was our use case and we are migrating away from custom elements to a more conservative approach.
kubb
Good luck with your better framework, but if this is the biggest flaw… then there’s really not much to complain about.
sauercrowd
causes a bunch of things to no longer work though - slots, style encapsulation, ...
kubb
If you need style encapsulation, use the Shadow DOM. Slots still work IIRC.
troupo
And that's the biggest problem with Shadow DOM (and most web component specs): you can't chose the good parts. Style encapsulation is useful, slots are useful, Shadow DOM is just all around bad, having a crazy amount of edge cases and broken behaviours [1].
Can you use style encapsulation and slots without Shadow DOM? Why can't you? I only need the horse, not the horse, and the cart, and the driver, and all the cargo in the cart.
You can't because people pushing all this stuff forward never ever stopped to think whether this was a good idea, and never ever talked to anyone outside of their own group.
[1] I will keep quoting this report by Web Components Working Group to death:
--- start quote --
It's worth noting that many of these pain points are directly related to Shadow DOM's encapsulation. While there are many benefits to some types of widely shared components to strong encapsulation, the friction of strong encapsulation has prevented most developers from adopting Shadow DOM, to the point of there being alternate proposals for style scoping that don't use Shadow DOM. We urge browser vendors to recognize these barriers and work to make Shadow DOM more usable by more developers.
...
Shadow boundaries prevent content on either side of the boundary from referencing each other via ID references. ID references being the basis of the majority of the accessibility patters outlines by aria attributes, this causes a major issue in developing accessible content with shadow DOM. While there are ways to develop these UIs by orchestrating the relationships between elements of synthesizing the passing of content across a shadow boundary, these practices generally position accessible development out of reach for most developers, both at component creation and component consumption time.
...
Selection does not work across or within shadow roots. This makes fully-featured rich-text editors impossible to implement with web components. Some of the web's most popular editors have issues that are blocked on this functionality.
--- end quote ---
soupy-soup
I've been working on a legacy server-rendered app that has a bunch of ajax calls, and stock web components and their shadow DOM has been super helpful to keep the mess at bay. Most of the work is actually making the app more accessible, actually.
The trick is that the components really do need to be self contained, and you need to use slots and custom attributes to bridge the gaps. Styling is the most annoying part for me, but I just include the same global imports that the main page has.
andrewingram
> so having two just because somebody wanted to optimize their resume was such a drag.
Does this actually happen a lot? Allowing for the fact that people would rarely admit to it just being about resume padding, I feel like just wanting to _use_ the thing is a far more common motivation for poorly rationalised technology choices.
gitaarik
I made a state management lib for Lit, that's just as lightweight (258 lines) and intuitive:
https://github.com/gitaarik/lit-state
I've used it extensively myself, for creating complex web apps with many (nested) components interacting with each other.
I don't understand why Lit hasn't gained more popularity, because for me it is basically React, but then more browser-native, much less boiler plate, and much faster rendering. There are some things you have to get used to, but when you do it doesn't limit you in any way.
Ruphin
Re-implementing Lit from fundamentals is a great way to learn how it works! The core functionality is surprisingly simple, because it mostly relies on platform APIs to do the heavy lifting, like parsing templates.
I made this alternative implementation of lit-html to use as a research bed a long time ago when I was actively contributing to lit: https://github.com/ruphin/lite-html
Judging from this thread, many people have their own implementations, which is great to hear. I think there's a lot of value in solutions that are so simple that anyone can reproduce them.
jfagnani
Lit maintainer here. I should be going to bed, but I'll answer any questions if people have any!
Not sure why Lit showed up on the front page tonight :)
polyrand
Hi! Not really a question, but just an appreciation message. I haven't used the full "Lit" package a lot, but "lit-html" is incredibly useful.
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.
jfagnani
Lots of comments in here are about shadow DOM, so let me give my take in one place:
Yes, Lit uses shadow DOM by default (for good reasons, I think!) and yes you can turn it off component-by-component, but that does bring some challenges.
Shadow DOM is most fundamentally just a private branch of the DOM tree for a component's internal DOM details.
Frameworks have this implicitly with DOM defined in a component's template vs passed as children. But that distinction isn't visible to other code, the browser, and CSS. This is both good and bad.
The biggest thing this separate tree gives us is the ability to tell what nodes are "children" - those are the light DOM children. Once you can separate children from internals, you can build slots. Slots are holes in the internals that children get rendered into.
Without something like shadow DOM you can't have slots. And without slots you don't have interoperable composition and you don't have viable container elements. You need some way to place children in an element that isn't confused with the element's own DOM.
So to me, before encapsulation and style scoping, interoperable composition is the most important feature, and that's really why Lit defaults to shadow DOM on. Without it we'd need some special `.children` property and Lit's component composition suddenly wouldn't be compatible with everyone else.
But the style encapsulation is often a major pain for developers, especially if they're trying to integrate web components into an existing system with whole-page stylesheets. It's a big blocker to a lot of design systems porting to web components.
That's one reason I proposed something called "Open Styleable Shadow Roots"[1] which would let styles from outer scopes cascade into a shadow root - a way to break open style encapsulation but keep slots. It's been hard convincing browser vendors that this is needed, but I'm holding out hope that it makes progress soon.
skybrian
Aren’t a lot of components leaf nodes, with no slots? Does the shadow dom have any benefits for them?
ulrischa
We used to put a link to the overall stylesheet in the webcomponents. That works pretty good
dtagames
Nice to see you here and THANK YOU for the amazing tool that is Lit. It's everything you want from a framework without a framework getting in your way.
I'm sold and build all my work and personal apps with it and have for many years. I wrote this article about why in 2022:
Getting Started with Web Components & Lit
https://medium.com/gitconnected/getting-started-with-web-com...
dboon
Thanks, great article. It’s always good to understand the context of where libraries fit into the web ecosystem and why they exist. Much appreciated!
krikou
Here just to say thank you for Lit! It is a real pleasure to use (for simple and complex use-case).
Sometimes, I am wondering why it is not more widely used ...
preommr
Any whispers of something like lit being made part of the webcomponents standard?
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.
jfagnani
Lit has always been designed partially as a prototype for where web component standards could go in the future. That's a big reason Lit is fairly conservative and un-opinionated. It doesn't try to undo or paper-over any of the DOM APIs, but add to them instead.
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...
lenkite
I hope there can be ways without JS to populate templates with data - autoloaded from sources. This would tremendously increase the number of JS free web-sites. Also wish the web-components standard did not mandate the use of JS. It should be possible to define simple web-components (HTML+CS) declaratively and have this officially supported in standard and implementation
undefined
troupo
> Lit has always been designed partially as a prototype for where web component standards could go in the future.
> There is a proposal in TC39 for native signals,
Which originated (or the modern versions of signals originated) in Solid, not in Lit.
Let me quote the readme: https://github.com/tc39/proposal-signals
--- start quote ---
The current draft is based on design input from the authors/maintainers of Angular, Bubble, Ember, FAST, MobX, Preact, Qwik, RxJS, Solid, Starbeam, Svelte, Vue, Wiz, and more…
-- end quote ---
akmittal
Curious which web platform features are missing that are preventing Web components to complete with React(for application development not widgets)?
jfagnani
I think web components already compete extremely well for application development, and you see very complex apps built with Lit out there: Photoshop, Firefox, Chrome OS, Chrome DevTools.
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
brazukadev
> - Open styleable shadow roots
What people using web components want is to get rid of shadowDOM and not feel like they are deviating from the correct path. shadowDOM sucks, stop trying to convince the world that we are using it wrong. shadowDOM is the whole reason web components did not become mainstream (yet?).
notnullorvoid
Please do not refer to CSS type imports in JS as CSS Modules.
CSS Modules has an established meaning for over a decade, one that is still relevant today. The CSS type imports are very different, and arguably worse.
Call them CSSStyleSheet imports of you need a name suggestion.
nisbet
About CSS Modules – Are you referring to this? https://caniuse.com/mdn-javascript_statements_import_import_...
Seems like this feature was removed from Chrome.
Muromec
>- ARIA reference target: make idref-based reference work across shadow roots
How is this even supposed to work if each shadow dom has it's own scope of ids? `#id#subid` or something?
What if I want to ref to the outside?
The whole thing is not made for web development.
troupo
You can start with the Web Components Community Report: https://w3c.github.io/webcomponents-cg/2022.html
Or with opinions like this: https://dev.to/ryansolid/web-components-are-not-the-future-4...
O if you want to go down the technical rabbit hole, you can search for all the issues people have with them, e.g.: https://x.com/Rich_Harris/status/1841467510194843982
Muromec
Another pain in the ass is the fact web components are registered globally. Good luck marrying this with npm dependency hell where two transitive dependencies both import a button.
The good part of react and friends is it's just javascript and the class is imported and referenced normally, not with a weak string-binding-through-registry kind of way.
Now add types to the mix and shadow dom and it brings constant problems without any upside.
dan353hehe
I am not the one who submitted it. But someone mentioned it last night:
https://news.ycombinator.com/item?id=45107388
I assume someone else looked it up and liked it enough to submit it.
iammrpayments
Are properties reactive?
Can I reassign name in the example by using document.querySelector?
jfagnani
Yes!
jcbrand
I used Lit components in a large FE project, enjoyed doing so and am happy with my choice. I don't use the shadow DOM at all.
The project is Converse.js, an XMPP chat client. It's an old project that was originally created back in 2013 with Backbone.js.
I first replaced all templates with `lit-html` when I first heard about that, and then when lit-element (and now "lit") came out, I started rewriting the project to use that.
This app has since been integrated into many different websites that rely on other frameworks like React and the fact that Converse.js is a web component (<converse-root />) makes this easier.
If you're interested, here's the Github repo: https://github.com/conversejs/converse.js And you can demo it here: https://chat.conversejs.org/
You'll need an XMPP account (see https://providers.xmpp.net/ for possible providers).
o_m
I don't see the need for Lit anymore. Lately I have just been raw dogging web components without any libraries. Having a nice templating system like JSX on the server makes it a breeze.
Part of using web components, for me, is that it is just javascript. There is no upgrades or deprecations to think about. Of course those things still exist on the server though, but it is easier to maintain it there.
jfagnani
The great thing about web components is that you can build them however works best for you.
Native web component APIs don't have the DX that many people expect though, because they are so low-level. Lit provides just that declarative reactivity on top.
mariusor
Personally I find that lit abstracts quite well some pieces of functionality that you're going to implement yourself anyway to not have to write manual <template> all over your code plus the plumbing to add it to the DOM.
o_m
Yeah, it does require some more boilerplate. I abstract some of it JSX, and with LLMs writing boilerplate code isn't that annoying anymore.
rs186
I find that there is little practical difference between "html" tagged template literal and writing JSX. Not to mention there is a compilation step in JSX.
fkyoureadthedoc
Don't know the current state of lit-html and similar, but Typescript support was the biggest thing missing for me when I used it several years ago.
In simple scenarios like just dropping it in an html page, codepen, or something like that I really enjoyed it though.
o_m
I mean sure, as long as it runs on the server. Personally I feel JSX is way more expressive. The JSX I write runs on server side rendering to HTML. That way there will be no flash of unstyled content, cumulative layout shift, or any other jank. It looks correct even before the javascript has been downloaded, except it isn't interactive yet.
kavaruka
I have been using Lit in production for 3 years now. I think it is the best abstraction over the web components API out there.
selectnull
Same here.
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.
brazukadev
Same about the shadowDOM. The only criticism I have about Lit is that the creators think shadowDOM is amazing and people not liking it are using it wrong. Lit lacks a good direction and someone with vision leading it but it became the technical pet project of a few.
selectnull
The ability to locally scope styles is a great feature of shadow DOM. For that alone I can see why it's being pushed.
It's trivially easy to create Lit components without shadow DOM so I don't really care and use both.
kubb
For the frontend work that I did, Lit was a godsend. It really helps you build components and apps without getting in the way.
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.
pmg101
Which old browser capabilities are you referring to? Could you say more, or link to more details?
kubb
No shadow DOM, no web components, no template strings, etc.
troupo
> No shadow DOM
Funny you should say that when the current advise for web components is to avoid Shadow DOM (almost like the plague)
> no web components
As in?
> no template strings
Why would React need template strings? React is not the only framework that doesn't use template strings for anything (Vue, Solid, Svelte come immediately to mind). And it's hard to accuse those of being behind the times when Solid is literally the reason for the upcoming native signals proposal
pmanu
That’s also why I really like Aurelia framework. Its component model feels very intuitive, and it embraces standards like custom elements and decorators instead of inventing new patterns. Compared to Angular’s boilerplate or React’s hook gymnastics, Aurelia lets you write less code that looks more like plain JS/HTML. Too bad Aurelia never got the same traction as the big frontend names, because the DX is really solid.
SebastianKra
I thankfully migrated or left all Aurelia projects, but every time someone mentions it, I remember new horror stories.
Its .html temples were shipped unmodified directly to the client (yes, including comments). Except they weren't actually html, and sometimes the browser would try to clean them up, breaking the template.
Reactivity was achieved through all kinds of weird mechanisms (eg monkey-patching arrays to watch for mutations). It would frequently resort to polling on every tick or break completely.
DI used TypeScripts experimental decorators, even long after it was clear that it would never become stable.
On the other hand, templates weren't type checked.
pmanu
Never had issues with the HTML. Templates sometimes showed comments in dev mode, but in production builds they were stripped and everything minified. I never used Webpack or other bundlers, only the "dumber.js" from their CLI, so maybe was something related to that?
And yeah, probably they monkey-patched arrays and such, but that was just the way of the world before proxies and native signals. The cool part is Aurelia stuck to web standards, and those “weird mechanisms” were basically polyfills, so even old versions still run solid today, sometimes even faster by leveraging native features.
SebastianKra
I thankfully migrated or left all Aurelia projects, but every time someone mentions it, I remember new horror stories.
Its .html temples were shipped unmodified directly to the client. Except they weren't actually html, and sometimes the browser would try to clean them up, breaking the template.
Reactivity was achieved through all kinds of weird mechanisms (eg monkey-patching arrays to watch for mutations). It would frequently resort to polling on every tick or break completely.
DI used TypeScripts experimental decorators, even long after it was clear that it would never become stable.
On the other hand, templates weren't type checked.
iamsaitam
"React is designed for the old browser capabilities and is now staying around by inertia, not by inherent quality." this makes me feel old and I guess React is famous for supporting Internet Explorer /s
mdhb
Hands down the most underrated front end library out there. It powers some major projects like ChromeOS, Chrome Devtools, I think most of Firefox’s UI, Photoshop for the web, MDN etc.
CharlieDigital
Also Reddit! Any other surprise sites?
shoeb00m
I think lit is great but the reddit site is the perfect example of why the framework you chose is not the reason your site is slow.
I think lit should distance itself from that mess if possible
CharlieDigital
Site seems fine to me on mobile and desktop (only use the web app in Firefox). Their main issues are with data fetching, not rendering.
mdhb
I just came across this resource the other day and found it super helpful, thought I would share it here for anyone who’s interested in working with Lit.
sibit
I really like the standalone lit-html rendering library but never really saw a need for Lit. Honestly, I find it hard to see a need for more than <any client-side rendering lib> + Web Components when I want client-side rendering.
mulhoon
Working with a large Vue 3 project and wanting to share some of our components as re-usable web components for other sites to embed...
What would be the benefit of rebuilding these components in Lit over using Vue to build them?
https://vuejs.org/guide/extras/web-components#building-custo...
rs186
I have used both. Personally I prefer Vue a bit more.
* Built-in state management especially as in v3 (ref/reactive) is super powerful, and you can test the setup function logic by itself without any dependency on DOM which is convenient. By comparison, reactivity in Lit is basic (by design), and mostly work on the widget level -- if something changes, you need to trigger the update process of the widget.
* The lifecycle is also a bit simpler. In Lit, you often need to work with lifecycle callbacks like firstUpdated, connected, shouldUpdate, updated, disconnected etc. (You don't need to implement these for simpler widgets, but often you have to.) You can easily run into bugs if you are not careful, especially in the less common situation where your widget can be both temporarily and permanently removed from the DOM, in which case you need to make sure the state of the widget is properly perserved, which isn't a thing you need to worry about in Vue. We got bitten by this multiple times.
Unless there is a strong technical reason, I suggest that you focus on shipping features instead of changing your tech stack. Rebuilding your widgets is a very time consuming task with, well, near 0 impact on the user.
mulhoon
Thanks for this. I think you're right -> "focus on shipping features instead of changing your tech stack"
Ruphin
I don't know if there is a particular benefit, it's just different. On the consumer side there is no difference, because they consume Web Components, and that is what both solutions deliver. On the implementation side, I can think of a few differences:
Vue is more of a "framework" solution and has more things built-in. You can do the same things with Lit, but the implementation would look different, because you'd lean more on native APIs. A good example of that is the event model, Vue has some event model built in, but with Lit you would use EventTarget.dispatchEvent().
Lit is a runtime solution, it doesn't require a build and you can load your source directly in the browser. Vue on the other hand requires some form of compiler stage to produce something your browser can use. Compilers these days are fast, and Lit is specifically engineered to not have runtime performance overhead, so in practice this difference is rather minor. It is a very fundamental difference, so I think it's worth pointing out.
Vue can compile to other targets. If you are only delivering Web Components, this is mostly irrelevant, but in theory a consumer might be able to use the Vue components directly in their Vue project, which might give them a better DX. On the other hand, Lit is specifically designed to produce Web Components, so you'll probably have a bit less friction compares to using Vue, e.g when some Vue concept doesn't compile cleanly to Web Components.
Is there a major benefit to choosing one implementation over the other? I don't think so, unless you have a very particular requirement that one of them addresses that the other doesn't. For nearly all cases, it is just a different implementation syntax.
In most cases the only relevant metric in deciding between them is what technology your developers are more familiar/comfortable with.
rs186
Vue can be used as an ordinary JS library without special build setup. You can even load the library from a CDN as a global variable like the old jQuery days.
alexisread
Thought I'd add an example:
https://github.com/SaleCar/Quasar-UMD-Template
You can do sophisticated things as well eg. Stream half a million Kafka records into the browser- anything available from unpkg or other cdns.
A good cdn UI lib turns out to be https://quasar.dev/
mulhoon
Thanks for the in-depth response, much appreciated
Muromec
>Working with a large Vue 3 project and wanting to share some of our components as re-usable web components for other sites to embed...
Make a fat bundle with a web component or even a mount() function exported and run whatever fits your devx inside, with the API surface as narrow as possible. As long as it's self contained and the size is reasonable, nobody on a consumer side cares how you cook, so optimize your own pipelines to build, test and publish it.
People will build adapters to fit it into their stuff anyway and will let you know.
tkubacki
Lit is fantastic lib as a way out from legacy web framework (since can be injected in any framework including Vue, Angular, React). I used it as a way out out of old Vue2 project
Get the top HN stories in your inbox every day.
I had lit in a project at work and not having to deal with it anymore is just great. We already have another heavier component framework to do the actual application stuff anyway, so having two just because somebody wanted to optimize their resume was such a drag.
It all looked nice in theory, but one thing shadow DOM makes worse is A11y, because element ids are now scoped and all the missing describe-by, label-for for things that should link to other side of the fence are a massive pain in the ass.
Big part of it is just skill issue on our part of course.