Your premise that the browser implementation is faster and better is rarely true. And when it is true, it's only true in a very narrow lane.
Take for instance something like suggestions on form fields: you start typing something and it presents some options from a hardcoded list that matches the prefix. This is natively achieved through the HTML element <datalist>. However, <datalist> implementations on most browsers suck to the point of being unusable.
The drive to roll your own is not so much that "it would be fun to learn this" as much as it's "rolling my own would let me express my vision exactly". What draws a lot of people to software engineering is that it lets you make anything you imagine. This is also what makes a lot of devs turn their nose at no-code and vibe-coding.
If you can't build things exactly how you want them to be, then it's hard/impossible to build something that's truly genius.
For one thing, I just genuinely think WebComponents are a badly designed API that is weird and hard to use (how many people are using WebComponents without at least Lit, if not something much bigger?), and React is a relatively well-designed library that isn't really that bloated. There's not really much of a point in trying to argue since this is inherently subjective and people with different values are going to irreconcilably disagree. But, if you don't respect that some people hold this position, we're not going to make any progress towards a consensus.
On the note of <dialog>, I recently tried to use <dialog> in a (React) application, and it did work pretty well, but I also found that in Firefox it is only practically possible to do a fade-in animation, not a fade-out one. That isn't really a critical issue for me, it is just an animation after all, but I find it unfortunate. I also find <dialog> to be a weirdly shaped API too: I don't really hate it, but I don't love it either. It feels awkward.
I find this implicit view that developers that, for example, prefer React over WebComponents are making a suboptimal choice to be rather condescending and not really in the spirit of trying to see things from the other side. Wouldn't you want to focus on the strongest arguments and not the weakest ones? Maybe you've literally never heard anyone complain about WebComponents or Shadow DOM, but if so, I find that surprising. Certainly here on HN, I've seen a fair bit of WebComponents hate.
I do, FWIW, realize that I've particularly focused on WebComponents, which this article doesn't actually name directly. But, I assume we're not talking about ditching React to implement our own component framework on top of the traditional DOM APIs, because that's what React already does...
Coming from a more general programming view, I find web development extremely odd. In general programming we tend to find a small set of abstractions which we can use in a composable way to cover our problem space.
For example, to interact with the VFS, we have read()/write(). When we add more APIs, it can be to enable a new paradigm, like epoll(), or for performance, like readv()/writev(). For a functionality that can be composed out of existing APIs in a performant way, we do not add it in the platform, but leave it instead to the domain of libraries. This separation has immense values, as it makes platforms easy to implement. A Linux filesystem, for example, needs to implement only 10 or so functions.
The web seems to be perfectly composable too, out of <div>, <span>, <p> and a small subset of CSS, but doing this is considered an anti-pattern, and you're supposed to reach for the platform to find the closest thing to what you need, whereas reaching for a library or composing yourself is frowned upon.
The result is that there are only three platforms: Blink/V8; WebKit/JavaScriptCore; and Geko/SpiderMonkey. With many things only working or working well on Blink/V8.
And implementing a new platform is a titanic task.
As a user of native apps, I can always tell when the developer (or, often, the UI designer) chooses to "fight the platform" and reinvent things themselves, instead of embrace the platform and use what it provides for free. Developers who insist controls should look like their own vision, instead of what the platform provides (and users of that platform expect). Apps built this way always look/feel a bit weird and off. Keyboard shortcuts don't work like you'd expect. Accessibility functions that you normally get for free are missing. Controls behave just so slightly differently for them to be odd to work with. The app "sticks out" among the rest of your native apps, and usually not in a good way.
So you end up with situations like: My time picker looks exactly like I want it to look, but it doesn't handle leap seconds. And: My login form behaves exactly like the vision our PM dreamed up, but autofill doesn't work anymore.
As far as I know there are still some things "the platform" actually won't deliver; for instance I'm fairly certain there's no searchable combobox that's fully accessible. One ~must leave the platform to give users the experience the expect.
That means "the platform" itself is actually teaching people to work "off platform" and arguably will always have gaps as functionality and expectations evolve.
Admittedly, the habit really ought to be 'I need to make a combobox -> does the platform have what I need? -> Research, evaluate, test -> Otherwise, make it' but I don't begrudge people for skipping the middle steps.
Kinda funny I was trying to log into the network at a Hilton last night with a Steam Deck and I had to lie about my state and zip code because it took about a minute for the state dropdown to get populated with states and once I picked Ohio instead of New York, I couldn’t get the dropdown to open again so I looked up an Ohio zip. It was one of a number of small technical glitches on the trip including USB chargers that had bad connections and worked intermittently.
Accessibility is important to our customers where I work so it is important to us…. And I have spent so much time fighting with third party controls to get them to work right.
The answer is UX designers and marketing people. I will yet have to work in a web project where any UX designer will be happy with what the native browser has to offer. Notable examples are date/time pickers. Look at any of the Top100 websites and you will find custom date/time picker designs. And I would also say, with standard browser built-in dialogs you could not rebuild/model those pickers to match what the Top100 websites use.
I feel like it’s a historical accident. In the past the platform couldn’t do it all, and if you wanted a dialog you had to use a library. Developers were trained to reach for libraries when they needed something like a dialog.
Then react came along and all developed learning web development after react had little to no knowledge of the platform. They were taught that touching the DOM was a bad thing to do.
That’s about it. Even now when I advocate for vanilla css I get the side eye and “tailwind and shadcn should be the default”. I get it, it’s what most people are familiar with, even if it’s worse than the platform.
For a lot of us it's lived experience - "the platform" can hide bugs that don't emerge until a certain rare set of conditions is present and we get glared at by the business folks who don't understand why we can't just "fix it" when it's buried in someone else's Jenga tower.
Many native web browser capabilities exist because adventurous developers came up with the patterns themselves. There is no way we’d have CSS scroll-driven animations available to us if front end developers hadn’t already established the requirement and pattern. Browser standards, CSS specs etc follow what _we_ hack together and make ubiquitous (sort of like desire paths), not the other way around. That is why we shouldn’t blindly “use the platform”; vendors should adjust to our demands, not the other way around. Of course, if a native element or capability matches exactly your requirements in some scenario, using it would be sensible.
I was early adopter of WebComponents and honestly they are terrible. If only they would have at least CSS layer which would be passed and I can reset styles and shadow root would be accessible ass private property and every element with id world be accessible through private property so I don't need to store them in weird way of query them.
Then I would consider them acceptable
In current state they are unusable beyond simple components
Ever used a time field in pure html? And then you get reports users can enter 99 minutes.
Yes that's why
I think this is completely wrong. The reason why nkt a lot of people use the built in elements is because sooner or later you will hit a limitation that you cannot fix. If it is a javascript element you can do whatever you want if it doesn'fit.
Take dialog as an example. If you have a server side rendered app and you want to show an open dialog without js. You are out of luck, you can't just render it as open because that opens a dialog that does not correctly work. Or take a multiselect input. Just unusable as a normal browser element. Also most elements miss something essential like no search function in an input. So also unusable for big lists. I could make a list of 100 things that are wrong with native browser elements. It is just easier to use a js framework/library and have a clean view and state.
When a technology becomes popular enough, it develops a community that solidifies that choice: conferences, books, extensions, a generation of engineers that see things in terms of React.
A technology needs to be a lot better to overcome that aspect.
Sometimes I visit a subreddit for a tech and see them all discussing strategies/techniques that are ultimately workarounds for what an alternative technology has fundamentally solved, but... the original tech has an army of volunteers able to help newbies workaround it, which is often an easier onboard experience than the alternative tech that just works, but doesn't have any advocating solutions/blog posts because there are no blog posts to be written.
An aside: This name an logo are incredible. https://bevacqua.github.io/dragula/
The last couple of websites I've made have been largely the output of Claude with some instructions to keep to WCAG AAA accessibility standards and to optimize for loading and rendering times, and it's done a pretty decent job. If you're insistent about page weight it will avoid adding JS and React and use to browser-native elements, CSS, and vanilla JS where it can.
I think the problem is that you have to ask, and to know the language to get the result you're after. If you just ask for a pretty website you're getting 800KB of React libraries to render something, and all in AI Beige with Inter as your font choice.
Because the platform sucks. I want a rounded button with a certain radius and a certain font, that feels squishy and satisfying when you press it, especially on mobile.
The main reason is flexibility.
One day your boss stands next to you and asks: "can you move this border three pixels to the left", and the only correct answer is "but that requires a complete rewrite".
From other comments that are focused on the code part of the subject, I think there are 2 big forgotten points here: time and hype.
Time: since platforms are big machines, their timeline and backlog is huge, and the self-taught geek does not consider (care) that. So when there is an obvious little hiccup somewhere, they create a bug report that asks for details, proof, reproduceability,... and finally get pushed back to eons because there are more pressing concerns to attend to at the platform level. Meanwhile, it takes about 1h (without AI) to code a workaround and feel like a hero because "I've fixed something that took them 3 years to triage".
Hype: yes documentation and code quality and all matter, but it matters even more when it comes from Google or Meta! We all feel little compared to giants and when they open their internal secret tooling framework (with big marketing budget) then we all feel like there is a secret to grasp and a key success factor to wield. So it is not so much whether a npm library some nobody created exists, but whether the main contributor works at a big brand name. It does not prevent smaller anonymous projects from emerging but lets face it, it is much more appealing when it is how Cloudflare handles it at 1e20 scale (because we all feel we face the same challenges of course).
<dialog> still has issues to this day that haven't been resolved - https://tane.dev/2021/02/revisiting-dark-patterns-with-the-h... - of course these can be implemented in any framework but this makes is much easier - at the platform level - to make a browser unusable, and as it's platform it's of course never been fixed.
You can have fun with web components (https://tanepiper.github.io/webc-humour/) but from my experience trying to build UIs with them - they end up becoming an additional abstraction that instead of just using a framework to build the entire experience, it creates annoying boundaries of having to deal with DOM attributes instead of just working with properties.
~a year ago i passed a major inflection point regarding web UIs.
i built an in-browser STT app UI with dear imgui, and everything just _worked_. i’m rendering to a canvas, running the model in a service worker and heavily using web audio, among other platform APIs. but.
at this point, i’d even struggle to comprehend the concept of going back to using the DOM for anything but a static reading experience. perhaps peppered with _fancy_ web components for an interactive animation. some would argue that’s what it’s for.
well, browsers/JS engines can both be powerful and terrible at the same time. despite using imgui via typescript bindings and rendering to a canvas via webgpu/webgl2, there is almost no limit to what i can do. more importantly, how easily i can express _whatever i want to see_ without paying with terrible frame rates, gc or layout jank or some other fun webism.
i’ve built SPAs since dojo was a thing, built iAds (lol), really, i’ve bikeshedded myself to oblivion.
low key expecting some kind of communal inflection point where we stop wasting our time arguing about bronze age tools and start having fun again.
The original sin of JavaScript was such a small standard library.
React, Vue, etc are all just working around it. I’ve never been good at web programming, but the rare times I need to, I want it to be easy. Thus Vue.
Infact I’ve been building my recent web projects with Flutter and Godot. Flutter Web is such a better experience if your use case allows it.
The problem is that HTML, Javascript, and CSS are the wrong "low-level" abstractions. They are high-level abstractions that various web development technologies like React work around. The problem is that they try to provide a standard that solves every problem; and the market generally rejects that standard so it tries to work around it.
The right thing would be for the browser to expose much lower-level abstractions. Webassembly is a step in the right direction, but it needs an API other than HTML and calling back to Javascript.
I have been down the rabbit hole. React for a web app used for scheduling. I built my own React/Elm-like framework in Rust/WASM. Use react at work.
All my web sites / web apps now are HTML + CSS + targeted/native JS. No npm or build steps. And I don't hit any limitations. They load and run faster than ~99% of websites.
Because every product manager thinks they know better. I and other engineers have pushed back to "use the platform" for years and years and more often than not we get told to do something custom to please product's fantasies, because "the platform" doesn't implement some inane custom request. So we make something custom and worse at great expense of user experience/expectations, implementation cost, and maintainability.
Not that I'm bitter about it or anything.
React to some degree made immediate mode UI possible in the browser, which is part of why it is this successful. If the browser gave the option to do ui = f(state) natively, you wouldn't need React.
Web components are lighter than frameworks, are they not? That was the biggest benefit I saw: no dependency on an ever changing framework and toolchain.
Decades old apps written in DOM and JS are eminently more maintainable than that written in some no longer maintained backbone / 1.4 django frontend or wherever, with their cacophony of unmaintained tools.
They didn’t seem quite as polished as the latest framework offering but they promised to be around when everyone gets bored of framework x.
It's because frankly the platform has been historically shit. Web components comes to mind as someone else here has mentioned, as it's just not a good API and needs wrapping to make it usable, same as IndexedDB which the author readily admits as a creator of such tooling. It seems like the ones who determine the platform aren't actually developers day in and day out and thus don't dogfood their own products while the rest of us do, leading us to reinvent the wheel.
Here is a great comment and discussion (scroll down) by Ian Hickson who wrote the HTML5 spec on how the platform has essentially failed on its promises causing everyone to write everything in JS or even other paradigms like Flutter and other WASM or canvas based frameworks that eschew the web entirely: https://news.ycombinator.com/item?id=34612696
Mostly this is true for “internal” platforms as well. Most enterprises have some “way to do things” - and once you get beyond a few developers someone is always rolling some of their own - rarely is it obtuseness, often it’s lack of training and even awareness of the equivalent of “dialog” even exists
Personally, and this is more of a general coding thing than specific to web development, I find a number of imported items are easy to code and write myself, and thus I have control over debugging rather than submitting myself to the process of reporting a bug then hoping it will be fixed in a timely manner. I also have feature control and can avoid feature bloat, and I have full knowledge of the code I am running.
This allows me to speed up development and have a streamlined custom implementation of that feature for my code. For example, I was unhappy recently with performance and feature set in RRDTool. Seeing that updates from the dev for that are quite glacial I wrote my own implementation, which took about 20 minutes, and now I have one less import, and in the process speeded up data retrieval, so I can have 60fps graph generation, discarded unused features, and added a couple of custom ones for my application.
Mostly because UX has some needs they want to fulfilled. At least that has been why we used custom pickers / dropdowns / inputs, you name it
can the title be changed to "Why don't more developers use browser native features?"
Counterpoint on Safari. Apple still ties browser updates to OS updates and there are a lot of old iPhones in circulation. Safari 16 is still a reasonable target and it’s missing a lot of modern features and has a lot of bugs to work around.
Every time I try to use the platform feature I get it working well in one or two browser on either desktop, android or iOS and then later find out it works pretty badly on one of the other platforms
> If you search for “sticky positioning” on npm, there’s no package that says “just use CSS position: sticky, you dolt.”
You could maybe find a component that all it does is apply position:sticky though?
Because using a platform requires reading and thinking carefully and occupying the mind of someone else. It means telling business people and designers no. It requires maturity and experience to understand the true cost of custom work.
> But for many developers, this sounds like fun! Think of how much you learn as you start building this thing.
I got a good chuckle when my brain finished this sentence with "and promptly forget so that you can learn it all over again years later the next time you need to touch that topic".
My guess, based on my own and closely observed experiences, is that you can take a developer’s project history and carve out two pretty distinct categories that have huge significance: (1) projects they are most proud of and (2) projects that have the largest value/impact. I know for myself there is very little overlap in those groups.
The former being dominated by bespoke things that worked better than anything available at that time, but filled a tiny niche: “not using the platform”.
While the latter are the boring things that were built with unexciting bulletproof tools that keep churning and adding business value day after day, year after year: “using the platform”.
I did. At some point Claude figured out I didn't even check the code and it "minified" the code. Now only Claude can change it. It's a small side project I wanted to do for a long time and now it's Done.
Things that are harder to do make your website seem more flashy.
Its like when rounded borders were hard to do without using clever tricks, people would try and add them to their website so that they looked different to everyone else. Once they became easy to do they weren't so desirable.
The equivalent today is wacky scrolling schemes where unusual things happen as you scroll down. Whatever is difficult can be used to distinguish your site.
> The argument is simple: why build something yourself, in JavaScript, when the browser can do it for you?
And when it becomes real, you've got yourself an argument
It doesn't matter how often Safari released as long as updates keep on being tied to os updates. A large enough percentage of people do not upgrade their OS fast enough for new features to be broadly usable.
There have been countless times where I wanted to use some new fangled platform API, but couldn’t because it was buggy/unsupported in one of the browsers or didn’t quite match my use case. It does t help that the platform abandoned some of its efforts to introduce better primitives in favor of higher level APIs.
It’s funny, the article proceeds to answer the question in great detail: familiarity, level of abstraction, documentation, etc.
I agree with his point that learning to do it yourself can be fun and lead to a flywheel of improvement where the next time you’re faster and the next time faster still.
In the past that was the recipe for success as a developer, nowadays with AI many feel that’s no longer the case.
People will just use the best tool for the job, putting aside some time it takes for practices to propagate.
Native date pickers suck, are ugly, and have no customizability, and look inconsistent between user agents. They don’t even really conform to the OS either (other than iOS). Everyone uses JS. Chrome’s native date picker shipped with a monospaced input font, for crying out loud.
Position sticky is amazing and the behavior is better than what JS can give you. A lot of people use it. Not much UI to make consistent between user agents.
Make the platform actually good and consistent and people will use it. Native APIs are always the better choice if they accomplish your need.
Some developers are locked in to using some in house UI solution that is slow to implement any new features from evergreen browsers and even is still shipping hacks for IE11, although it was depreceted company wide years ago.
People really used to search for “sticky positioning” or things like that on npm?
I always just googled stuff, now I prompt
> If you search for “sticky positioning” on npm, there’s no package that says “just use CSS position: sticky, you dolt.”
Sure you use sticky till your component gets embedded inside a relative positioned container that you have no idea of where it is and why, and in complex codebases hardly you would rewrite the code for that container in order to not create regression. You then go with "use the platform" but javascript and you try using that horrible intersection observer api with an hack to make elements sticky, except it breaks immediately after on a corner case. You then reach out for a mature library.
Fuck off the platform i've been suffering for decades at this point fighting half complete apis and non well documented behaviour(no i wont read the humongous spec).
Everytime I used the platform(even recently with dialog) you almost immediately hit all the limitation.
The sooner we understand the platform abadoned us(and I also have a thinfoil hat theory about that) the soon we can have an api for drawing the heck we want(please dont mention canvas 2d) and an api for accesibility
This got to me: > For a certain type of developer, building things yourself is just more fun
The platform APIs were terrible. React wasn't "more fun"... it just made it possible to do things with the platform that were extremely difficult and cumbersome to get working reliably with platform APIs alone.
To me, web components were an incredible idea poorly implemented. Most of the minimal adoption happened on top of frameworks like Lit that wrapped WCs to try to make the dev experience tolerable.
In urban planning they have a concept called "desire paths" where if you don't put sidewalks and pathways in the right places, people invent their own. I feel like the web community has spent a lot of time and effort patching the platform.
Now credit where credit is due: it has very much improved. And modern standards means it really is time to re-evaluate where and when you need these patches. But don't write off all that annoying and painful effort people put in to trying to making the platform deliver it's promised potential just to "building it yourself is more fun".