Top
Best
New

Posted by begoon 11/1/2025

Do you know that there is an HTML tables API?(christianheilmann.com)
253 points | 202 comments
chrismorgan 11/1/2025|
A lot of people here are clearly not reading the article.

It’s not about the <table> element itself—we hope everyone knows about tables—but rather about the table-specific DOM interface, including things like HTMLTableElement.prototype.insertRow() and HTMLTableRowElement.prototype.insertCell() as alternatives to the generic DOM techniques like Document.prototype.createElement() and Node.prototype.appendChild().

These are handy if you’re hand-writing your DOM interactions, but libraries that construct and maintain DOM trees (e.g. React, Svelte, Vue) will never use them, and that’s the direction everything has headed, so in practice they’ve fallen into near-complete disuse.

They match HTML syntax in another important way: HTML tables have thead/tbody/tfoot section elements, but you can mostly skip writing them in HTML syntax because it’ll imply <tbody> open and close tags. Likewise in this interface, if you have a thead/tbody/tfoot element you can call .insertRow() on it, but you can also call .insertRow() on the table, and it’ll put it in the last tbody, creating one if necessary. Meanwhile, I presume in React/Svelte/Vue/whatever you must write out your tbody manually.

I’ve definitely used at least .insertRow, .insertCell, .createTHead, .rows and .cells in the last five years in no-library throwaway/demo scripts where I was generating tables.

—⁂—

Concerning the specific example given, here’s what I find a clearer code style, using for instead of forEach, using better variable names, and omitting the index argument to insertRow/insertCell which was quite unnecessary and only confused matters (the author doesn’t seem to have realised it’s optional):

  let data = [
      ['one','two','three'],
      ['four','five','six']
  ];
  let table = document.createElement('table');
  for (const row of data) {
      let tr = table.insertRow();
      for (const value of row) {
          tr.insertCell().innerText = value;
      }
  }
  document.body.append(table);
joquarky 11/1/2025|
I feel like frameworks have taken over and so few people know the foundations anymore. Thank you.

I still remember reading a news article on C|net about the addition of the <table> element.

Yeah, I'm old.

zX41ZdbW 11/1/2025||
I was using it just half a year ago, after either reading MDN or reading what AI suggested. Which means, this API is not obscure and not forgotten. Using `rows` and `cells` is very convenient for keyboard navigation across table cells.

https://github.com/ClickHouse/ClickHouse/blob/master/program...

conception 11/1/2025|
The worst thing on the modern web is people using divs for table data. What do you mean this table isn’t sortable? M365 Admin is the worst offender I’ve come across on this. Just terrible table implementations on almost every page.
mr_toad 11/1/2025|||
Is there a term for the opposite of cargo culting? Where everyone avoids something, but no one remembers why? Because that’s basically where HTML tables have ended up.
embedding-shape 11/1/2025|||
I think this is something like a "delayed cargo culting", or "cargo culting based on outdated facts". I think it's basically the same as the hypothesis from the "Monkey Ladder Experiment", where monkeys got punished when trying to get a banana, and eventually all the monkeys were replaced with monkeys that didn't realize why the banana was off-limits, yet persisted in trying to "help" other monkeys trying to prevent them from getting the banana.

I'm not sure if I read that that specific experiment was debunked or not, but it certainly sounds familiar to how some developer trends get propagated even though the ground truth as changed.

joquarky 11/1/2025||||
I would guess that people became so afraid of being accused of using tables for layout that they don't use them at all.
paradox460 11/1/2025|||
It's still cargo culting
ralusek 11/1/2025|||
Using HTML Tables doesn’t just make your data sortable
stared 11/1/2025||
It is similar as with buttons (https://news.ycombinator.com/item?id=45774182).

Not sure when it was (10-15 years ago), but at some point everything became <div>s. So, instead of semantic markup, HTML became a UI toolbox.

nonethewiser 11/1/2025||
That's because the DOM is mostly used as a render target instead of a semantic document.

I think semantic HTML is a great idea but it's kind of jaded to expect it at this point.

It also doesn't help that semantic elements have styling. That right there gives people good reason to use a neutral container as a baseline. In fact I would go as far as to say that having both div and span is a bad design decision. They are just aliases for css `display` values.

joquarky 11/1/2025||
The semantic web never took off because companies don't want to make their content easy to scrape.

Just look at how they salivate for WASM where everything is closed up and inaccessible, including a11y.

cruffle_duffle 11/2/2025||
That is one reason. Another reason is everybody’s way of organizing content is different. There would need to be an infinite set of semantic tags to really make it work.
art0rz 11/1/2025|||
I've been writing HTML for at least 20 years professionally and this has absolutely not been my experience. Yes, I've encountered some people using divs for everything but in the vast majority of cases people have used semantically correct HTML, at least when it comes to buttons.
lelanthran 11/2/2025||
> Yes, I've encountered some people using divs for everything but in the vast majority of cases people have used semantically correct HTML, at least when it comes to buttons.

I dunno; ISTR that the materializecss library used `<a>` for buttons.

macintux 11/1/2025||
I think it was inevitable. Most of the funded content on the web is marketing/sales-driven, and companies paying for marketing content want it to be displayed in a specific way.

It’d be interesting to have a parallel DocBook web for technical content, where consumers of that content could apply their own styles to render it in a way that’s best for them.

jazzypants 11/1/2025||
I mean, you can just remove all the user agent styles and then <button> is just as stylable as <div>.
macintux 11/1/2025||
Why would marketing want to pay for the extra (and to their mind entirely pointless) work required to capture semantics?

(I’m not saying I like the world we live in, but I don’t see a likely alternative.)

withinboredom 11/1/2025|||
Because not everyone has useful eyeballs. Some people are blind. The amount of extra work you have to do to make a div faithfully act like a button is far more than simply resetting some styles.
macintux 11/1/2025||
It seems evident to me that semantics are more challenging to define than visuals; it's not the CSS that's the problem.
lwhi 11/1/2025||
It's more challenging to encourage correct implementation of semantics than implemention of visuals; which is a great reason for using the element that was designed for this use case.
mpeg 11/1/2025|||
I've literally never had a marketing person tell me whether I should use a <button> or <div>. Let's not pretend things like using the wrong semantic elements is anyone else's fault but lazy or inexperienced developers.

These days it's a moot point anyway, because everyone is using things like tailwind which provide a full reset for things like default buttons, so there really is no excuse.

smusamashah 11/1/2025||
I used this for a small tool I was making to see stable Diffusion images in a table to compare images on different set of parameters, had lots of rows and columns. I needed to regenerate tables quickly, I vaguely remember this API being much slower than making rows/cells via strings. The reason I found was that each call using this API updates DOM and with string it's all in one go (or something similar).
StrauXX 11/1/2025||
> Without having to re-render the whole table on each change.

Not quite sure what the author means by that. Re-rendering pnly happens when the current task queue elemt has been processed. Never while JS is running (aside from webworker and the like). I would honestly be surprised if this API had much (if any) performance benefits over createElement.

mpeg 11/1/2025|
I quickly looked into the webkit code and there's probably absolutely no performance benefit, the same logic should be running behind the scenes
xg15 11/1/2025||
> Without having to re-render the whole table on each change.

That's nice, but isn't that what the standard DOM methods are already doing? Or does that API have any additional abilities?

Nevertheless, that's really cool and potentially saves a lot of tedious and error-prone DOM navigation.

runarberg 11/1/2025||
I feel like IndexedDB is becoming this abandonware as well. There are so many ways where this (IMO rather badly designed) API can be improved but the standards committee seems completely uninterested. Even things like adding BigInt as primative is unimplemented.

I fear this will be even worse now that we have the origin File System API and people can bring their own database engines (like web-assambled SQLite). But for those of us that are striving towards smaller download sizes this is a disaster.

indolering 11/2/2025|
What has stalled with IndexedDB and BigInt?
runarberg 11/2/2025||
Lack of interest from standards committee and browser vendors seems to be the only thing stalling:

https://github.com/w3c/IndexedDB/issues/230

I personally think that this stall is simply a symptom of the larger issue that the IndexedDB standard was bad to begin with, and that lead to lax adoption from developers, which deprioritized vendors from fixing the standard, leading to a vicious cycle where even a seemingly trivial issue like adding BigInt support goes unimplemented.

I personally think that IndexedDB is salvageable, and not only that, it has the potential to be an amazing web API. But the way things are progressing with the standards committee, I very much doubt it will be any better in the foreseeable future.

indolering 11/2/2025|||
Yeah, they definitely stopped investing in the APIs themselves. If someone can make a polyfill to shoe-horn in the functionality, then they don't really see a need. Which is sad, as we have outsourced our future to TypeScript, React, etc.
est 11/1/2025||
please rediscover html form API
zkmon 11/1/2025||
Abandoned? When? I still use this pretty much everywhere to create HTML tables. Do people use something else now?
moritzwarhier 11/1/2025||
Abandonware is a clickbait title insofar as it normally refers to licenses, not standards.

The idea of the author seems to be that this part of the DOM API that could benefit from backwards-compatible additions. So, by "abandoned", he hints at the headroom for building more table capabilities into the platform.

He compares it loosely to the form element API and the additions it received over the last decades.

In the case of tables, I could think of things such as a sorting, filtering API, but I can't tell whether that's what he means.

__jonas 11/1/2025|||
People often use declarative UI frameworks such as React, Svelte etc. when they want to build things dynamically in JS like that now, so imperative DOM manipulation APIs have unsurprisingly become a little more niche.
littlestymaar 11/1/2025||
If by “Niche” you mean “not hype” then yes, but the PHP+jQuery combo is still very widely used in 2025 (likely more than React, given WordPress market share alone).
__jonas 11/1/2025||
Sure! But if you render server side (as with PHP), you'd likely just build up your table on the server rather than dynamically on the client, so you would also not use these imperative table element specific APIs.

Even if, for some reason, you were filling in the table content dynamically via jQuery, I think the fashion there was also to just pass in whole HTML markup snippets as strings to be injected into the DOM, so you'd also more likely use plain <tr> elements than this table-specific API, same as with a 'hype' framework of now.

littlestymaar 11/2/2025||
JS hasn't been invented to render on the client side but to allow interactivity.
__jonas 11/2/2025||
What does that have to do with anything? The question was what do people use ‘now’ instead of this imperative table manipulation API, I’m unsure where you disagree with me.
littlestymaar 11/2/2025||
It has to do with your previous comment…

> But if you render server side (as with PHP), you'd likely just build up your table on the server rather than dynamically on the client, so you would also not use these imperative table element specific APIs.

__jonas 11/2/2025||
I feel like this is going nowhere...

The question was: What do people use now to create HTML tables instead of the table manipulation API described in this blog post.

I said:

- If you render a table on the client (not what JS was originally built for, but what it is often used for now) using a framework like React, you declaratively render the table using its semantic elements (table, thead, tbody, tr, td etc.) instead of imperatively building it up using that API

- If you render a table on the server, you essentially do the same (output the table markup)

That's why I described the above mentioned table API as "niche", which you seem to have taken offense with but I still have no idea why.

Maybe you're suggesting that this API is commonly used to add interactivity to a table element on a page with JS? I could see it being used for that, no idea if it is, I still have the feeling that just using regular Element APIs is more common - the question was also about creating tables specifically, not manipulating them, so that's why I mentioned declarative frontend frameworks.

littlestymaar 11/3/2025||
The problem is that you keep representing the world as a false dichotomy.

A website can be fully rendered on the server at load time and still being interactive on the client side after that initial load.

In that situation, if you want to interactively create a table on your webpage, then you can either use generic DOM methods (which I suspect is the most common way), or you can use the dedicated API.

That's how we did websites back in the 2000s and that's still how most of them are made in practice because the “legacy” tech never went away even if it has minimal visibility on tech forums like HN.

__jonas 11/3/2025||
Alright, thanks for explaining your point of view, I appreciate it!

It wasn't my intention to misrepresent anything, I can see how my original comment was perhaps a bit too broad, all I meant to point out was that when building tables dynamically on the client, a declarative framework is now (I thought) a common approach, how common it really is I have no idea, and I do not mean to diminish regular imperative DOM manipulation or label it as 'legacy' by any means.

jckahn 11/1/2025||
Yes, React
embedding-shape 11/1/2025|||
Why would it matter what library you use? I'm using React, I do <table> whenever I need to display tabular data, React or no React as no impact on when I'd use <table>.
iammrpayments 11/1/2025|||
Just make sure to pass a subscriber to useSyncExternalStore if you decide to venture outside React and use HTMLTable.insertRow, you see react is really smart and won’t let you use this piece of outdated code without punishing you with side effects.

Thanks Vercel & Meta for protecting us.

embedding-shape 11/1/2025||
> Just make sure to pass a subscriber to useSyncExternalStore if you decide to venture outside React and use HTMLTable.insertRow, you see react is really smart and won’t let you use this piece of outdated code without punishing you with side effects.

Huh? Why'd you involve state in this or any imperative code? You render the rows/columns as you'd render any other DOM elements in React, pass in the data as props and iterate on it, create children and pass them to render.

withinboredom 11/1/2025||
InsertRow updates the live DOM and React just wholesale replaces it. It’s a masterstroke footgun.
embedding-shape 11/1/2025||
Yes, your point? Anyone who spend 15 minutes learning about React learns that you don't manipulate the DOM directly, you let the rendering engine handle that for you.
iammrpayments 11/1/2025||
Yes that’s why of instead of learning the standard apis, you have to spend 15 months learning how to debug useEffect
embedding-shape 11/1/2025||
Or just skip all of the newly released stuff and use React as it was originally made, like me and many others still do. Never suffer from having to debug "useEffect" because we literally never use it. You don't have to use the newest and shiniest toys, especially not those with footguns.
moritzwarhier 11/1/2025||||
React is as orthogonal to DOM manipulation API as it is to letting the browser render tables from HTML.
zkmon 11/1/2025||||
And what does that use internally to manage tables? Just because there is layer between you and the API, it doesn't mean API is abandoned.
__jonas 11/1/2025||
Are you implying that when doing DOM reconciliation, React uses these table-specific insertRow/insertCell APIs for adding and removing elements in tables instead of the regular DOM element APIs it would use for all other elements? I would be surprised if that's the case.
mpeg 11/1/2025||
The funny thing is the insertRow/insertCell API just call into DOM manipulation functions like appendChild internally, they just provide some syntactic sugar around things like managing the rows/cells array. It's all the same

https://github.com/WebKit/WebKit/blob/28fa568972a4d34d867948...

iammrpayments 11/1/2025|||
Why would anyone use this outdated code over useInsertRow() and useTableColumnEffect()?
NetMageSCW 11/1/2025||
What are those and where are they in standard Javascript / DOM API?
righthand 11/1/2025|
Will Google remove this API then if it’s abandoned?

Topic is reminiscent of a submission from yesterday about XSLT:

https://news.ycombinator.com/item?id=45779261

simonw 11/1/2025|
XSLT requires hundreds of thousands (maybe millions?) of lines of security-sensitive code. That's why it's proposed for removal.

I doubt that's true for .insertCell() and .insertRow().

righthand 11/2/2025||
But the precedent isn’t fix the security sensitive insertCell() API, it is to remove it due to low usage. The number of lines is irrelevant IMO.

The Google deprecation notice fails to address why a gigantic company with nearly unlimited resources couldn’t implement this feature themselves instead of forcing a breaking change.

More comments...