[HN Gopher] Do you know that there is an HTML tables API?
       ___________________________________________________________________
        
       Do you know that there is an HTML tables API?
        
       Author : begoon
       Score  : 233 points
       Date   : 2025-11-01 12:58 UTC (10 hours ago)
        
 (HTM) web link (christianheilmann.com)
 (TXT) w3m dump (christianheilmann.com)
        
       | dtagames wrote:
       | Tables died (thankfully) to make room for flex and grid. I can't
       | see any use case for them at all anymore.
        
         | begoon wrote:
         | I personally disagree. When data is semantically a table, not
         | just a "table-looking" layout, I would rather use the table
         | tag.
        
           | the__alchemist wrote:
           | I think this is the gist of it. Tables were abused as general
           | spaced 1D, and 2D styling components. Introducing proper
           | general spacial styling components means we don't need to
           | extend tables beyond their original purpose, but doesn't mean
           | we shouldn't use them for that purpose!
        
         | zetanor wrote:
         | The use case for a table is to present data.
        
         | SahAssar wrote:
         | Tabular data? Tables have a purpose, it's just that people
         | misused them for layout purposes.
        
           | loloquwowndueo wrote:
           | To be fair, we did that when there wasn't much choice for
           | laying out web pages other than using tables. I was there!
        
             | cogman10 wrote:
             | Especially in ways that worked cross browser.
             | 
             | Young folk don't understand just how wildly different IE5
             | was to the Netscape or the Mozilla browser. Or just how bad
             | Javascript was when it started to be used on the internet.
             | 
             | I've lived through and seen the evolution. For all the shit
             | the JS community takes for constantly revving frameworks,
             | it's 1000x easier to make a website that looks the same
             | regardless of browser due to a lot of these frameworks and
             | browsers themselves evolving.
        
             | dvratil wrote:
             | It's not that long ago that tables were the only reliable
             | layout tool for HTML emails (mostly due to Outlook
             | supporting only very limited subset of CSS).
        
         | embedding-shape wrote:
         | How about displaying data in rows and columns in a accessible
         | and easily styled way, without having to rely on JS and your
         | own CSS to replicate a table? How exactly would you do that
         | with HTML and CSS without using tables? Using flex and grid for
         | those purposes don't make much sense unless you care about
         | design above all else.
         | 
         | <table> just gives you so many good defaults (semantic
         | structure, accessibility, column styling, column alignment,
         | keyboard navigation) for free compared to using CSS to create
         | your own table, that I'm not sure why you wouldn't use <table>
         | for tabular data.
         | 
         | Of course, if you need masonry, card grids and so on it makes
         | sense, do actual layouting with layouting tools. But thankfully
         | <table> hasn't died just yet, it's still better than CSS for
         | many use cases.
        
           | dtagames wrote:
           | Nothing about flex or grids requires JS. That's entirely CSS.
        
         | andai wrote:
         | This implies that you were considering -- for a split second --
         | making a 90s style table based website layout, using the Tables
         | API? ;) I might have to try that now...
        
         | pikuseru wrote:
         | They're probably still quite useful for displaying tabular data
         | - there's also semantics involved, it's not primarily just a
         | layout mechanism.
        
         | theandrewbailey wrote:
         | How about displaying data in rows and columns, like records in
         | a database? Or have you forgotten SQL, because you retrieve
         | JSON from your 1000 NoSQL microservices?
        
           | dtagames wrote:
           | Rows and columns are exactly what grid was added to CSS for.
        
             | theandrewbailey wrote:
             | Using only CSS for tabular row and column data is just as
             | wrong as using tables for layout. There are legit reasons
             | for using <table> today that can't be replicated by CSS.
             | Namely, CSS doesn't confer the same semantic meaning into
             | markup that <table> does.
             | 
             | Compare https://developer.mozilla.org/en-
             | US/docs/Web/HTML/Reference/...
             | 
             | with https://developer.mozilla.org/en-
             | US/docs/Web/CSS/CSS_grid_la...
        
         | nophunphil wrote:
         | I agree with many other replies here, specifically about
         | accessibility. Once I learned how to use a screen reader, it
         | was eye-opening. So many web applications are utterly broken
         | for users with assistive technologies.
         | 
         | Tables built with flex and grid absolutely can be made
         | accessible with WAI-ARIA, but native table elements are harder
         | to mess up.
        
       | thatwasunusual wrote:
       | > That way they'd finally get the status as data structures and
       | not a hack to layout content on the web.
       | 
       | I remember doing this 25 years ago, but I assume (and hope) it's
       | a huge minority who do this today?
        
         | embedding-shape wrote:
         | _cough_ view-
         | source:https://news.ycombinator.com/item?id=45781293 _cough_
        
       | bstsb wrote:
       | intermittent loading errors (503 Service Unavailable)
       | 
       | https://archive.ph/APbi8
        
       | zX41ZdbW wrote:
       | 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 wrote:
         | 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 wrote:
           | 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 wrote:
             | 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.
        
             | paradox460 wrote:
             | It's still cargo culting
        
             | joquarky wrote:
             | I would guess that people became so afraid of being accused
             | of using tables for layout that they don't use them at all.
        
           | ralusek wrote:
           | Using HTML Tables doesn't just make your data sortable
        
       | skerit wrote:
       | Interesting, but the JavaScript examples hurt:
       | let table = [           ['one','two','three'],
       | ['four','five','six']         ];         let b = document.body;
       | let t = document.createElement('table');
       | b.appendChild(t);         table.forEach((row,ri) => {
       | let r = t.insertRow(ri);           row.forEach((l,i) => {
       | let c = r.insertCell(i);             c.innerText = l;
       | })         });
       | 
       | Use full words for variable names!
        
         | niek_pas wrote:
         | I was just about to comment the same. I'm sure people have a
         | good reason for it (or at leafy _a_ reason), but single-letter
         | variable names always struck me as optimizing for the wrong
         | thing.
         | 
         | As someone who likes to program in Haskell, I feel this pain
         | very strongly. :)
        
           | bottd wrote:
           | Do you always feel this is the case? To me the go to single
           | letter variables are very readable. Used so widely my eyes
           | parse them like other symbols: =, &, +, etc.
        
             | alentred wrote:
             | My rule of thumb: only using single letter variables in
             | one-liners (and never if it spills to another line), or for
             | something that is conventionally represented as such. So
             | for example:                   ```python         bar =
             | [foo(e) for e in elements]         ```
             | 
             | or, using `x`, `n`, `s` and similar when they represent
             | just that, a generic variable with a number, string, etc. I
             | think there is a Code Complete chapter about it.
        
               | jazzypants wrote:
               | Yeah, I'm not GP, but my exceptions to this rule are `i`
               | for "iterator" in `for` loops and `e` for "event" in
               | event listeners.
        
               | NetMageSCW wrote:
               | Don't use 'i' (looks like 1), use 'j1', etc - helps set
               | you up if you need a nested loop someday. Of course, at
               | that point better naming would probably be best.
        
           | adamddev1 wrote:
           | Strong BASIC memories. On the Apple IIe, anything after the
           | first two characters of variable names was ignored.
        
           | croes wrote:
           | In real ok, but in this short example it's pretty obvious
           | what t,b, r and c mean
        
         | ninjin wrote:
         | Really? The variable name lengths? Not that the code is clearer
         | as:                   const te =
         | document.createElement('table');
         | document.body.appendChild(te);         [             ['one',
         | 'two',  'three'],             ['four', 'five', 'six'  ],
         | ].forEach((r, i) => {             const re = te.insertRow(i);
         | r.forEach((c, j) => {
         | re.insertCell(j).innerText = c;             })         });
         | 
         | My personal stance on short variable names is that they are
         | fine as long as their scope is very limited, which is the case
         | here. Rather, the "crime" to me is an overuse of rather
         | pointless variables as the majority of them were only used
         | once.
         | 
         | Disclaimer: I have not tested the code and I only write
         | JavaScript once every few years and when I do I am unhappy
         | about it.
        
           | matt_kantor wrote:
           | Looks like your code inserts a new row for every cell.
        
             | ninjin wrote:
             | Cheers! Fixed.
        
           | jonathrg wrote:
           | This is not an improvement. Having named variables for things
           | is good actually. They will need to be declared again
           | immediately once you want to modify the code.
           | insertCell(i).innerText = c is a nonsense statement, it
           | should be 2 lines for the 2 operations
        
         | AlienRobot wrote:
         | Personally I'd make everything const instead of let and use for
         | of instead of forEach, but it's like 10 lines of code it
         | doesn't really matter.
        
           | Sharlin wrote:
           | Are you sure this old API does the right thing with for...of?
        
             | kaoD wrote:
             | It's only used to iterate the array
        
               | Sharlin wrote:
               | Oops, right, I confused the variables.
        
             | runarberg wrote:
             | Should work just fine:                   >
             | document.createElement("table").rows[Symbol.iterator]()
             | // Array Iterator { constructor: Iterator() }
             | 
             | HTMLTableElement.prototype.rows actually just returns a
             | HTMLCollection, so same as document.forms, or
             | document.getElementsByClassName. HTMLCollection implements
             | Symbol.iterator as you would expect.
             | 
             | https://developer.mozilla.org/en-
             | US/docs/Web/API/HTMLTableEl...
        
         | layer8 wrote:
         | A bike-shedding thread on top as usual.
        
           | poisonborz wrote:
           | Code quality is not bike shedding.
        
             | Sharlin wrote:
             | It is, however, off topic and beside the point. And whether
             | short names are a code quality issue is a rather contested
             | and context-dependent topic.
        
             | nkrisc wrote:
             | Code quality of... an example snippet?
        
               | davidmurdoch wrote:
               | Especially
        
               | blackcatsec wrote:
               | especially now that the example is gonna end up in some
               | LLM somewhere and folks will just copy pasta.
        
           | refulgentis wrote:
           | Usually I'd cosign, but I get it, after a similiar issue I
           | had a couple days ago with a Rust article that was _insanely_
           | frustrating to deal with.
           | 
           | It's a brain scramble because you can't just read in toto.
           | 
           | Well, you can _literally_ , but, you don't feel like you grok
           | it.
           | 
           | And when you take a second pass you gotta slow down and stop
           | and parse "what's r here? is it relevant? oh rows?"
           | 
           | It's one of those things that's hard to describe because _it
           | doesn 't sound like much if you got it_. And this example is
           | trivial, especially if you're not open to the idea its a
           | problem (r/c = rows/columns) But it's nigh-impenetrable in
           | other scenarios.
           | 
           | You feel like you're barely understanding something that you
           | actually might grok completely.
        
             | embedding-shape wrote:
             | > It's one of those things that's hard to describe because
             | it doesn't sound like much if you got it. And this example
             | is trivial, especially if you're not open to the idea its a
             | problem (r/c = rows/columns) But it's nigh-impenetrable in
             | other scenarios.
             | 
             | I agree, it's highly context-specific.
             | 
             | In a small demo for a small blog post with basically no
             | complexity? Go ahead, use 1 character variable names, it
             | really isn't difficult.
             | 
             | In the 1000 long CUDA kernel where you barely understand
             | what's going on even though you understand the concepts?
             | I'd be favoring longer descriptive names than one letter
             | names for sure.
        
           | bfkwlfkjf wrote:
           | Yeah I see this a lot on HN. I think people feel the need to
           | make precise and accurate statements about things. I think a
           | lot of them, if they'd deep breath and waited 30 minutes,
           | they wouldn't comment.
        
             | embedding-shape wrote:
             | The internet is filled with pedantics, creeps and dogs
             | posing as cats. The whole "take a breath" thing was early
             | abandoned in favor of the now traditional "reply until the
             | other party gives up" approach, which requires you to
             | really dig into their messages and point out spelling
             | mistakes, fallacies, and for programmers, variable names.
        
           | skerit wrote:
           | It's hard to read, especially in the lambdas.
           | 
           | It's a small critique, I'm sorry it got upvoted by other
           | people.
        
           | dang wrote:
           | I understand the frustration (probably no one feels it more
           | than we do, because it's our job to help discussion stay
           | meaningful). But please don't respond by posting like this.
           | 
           | It takes time for the contrarian dynamic to work itself out (
           | https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que.
           | ..), and once that happens, the original problem subsides but
           | and the secondary problem (shallow objection to the
           | objection) sticks out like a sore thumb.
           | 
           | It's usually enough to downvote (or, in egregious cases) flag
           | a post that shouldn't be at the top. In really egregious
           | cases, emailing hn@ycombinator.com is also a fine idea.
           | 
           | From the guidelines: " _Please don 't sneer, including at the
           | rest of the community._" -
           | https://news.ycombinator.com/newsguidelines.html
        
         | phoronixrly wrote:
         | Looks to me like it's following the JS conventions... Jk, no
         | such thing exists still!!
        
         | Sharlin wrote:
         | It's normal to use short names for things with short scopes.
        
           | foofoo12 wrote:
           | Yes, and the reason for why that's OK is that the context is
           | just few lines. But this is borderline due to the amount of
           | variables.
           | 
           | In just 4 lines you have r, row, t, ri, l, i and c.
           | 
           | The full variables names are so short anyway that personally
           | I'd write them out. Code does evolve and there's a risk of
           | this suffering as a result.
        
             | Sharlin wrote:
             | That's a fair point.
        
             | NetMageSCW wrote:
             | rowIndex isn't that short.
        
               | bdangubic wrote:
               | shortness is in the eye of the beholder... program with
               | spring framework long enough and rowIndex sounds like
               | abbreviation. :)
        
               | foofoo12 wrote:
               | RowIndexFactoryGeneratorService
               | rowIndexFactoryGeneratorService = new
               | RowIndexFactoryGeneratorService();       RowIndexFactory
               | rowIndexFactory = rowIndexFactoryGeneratorService.getTheF
               | actoryOrSomethingIDontCare();       RowIndex rowIndex =
               | rowIndexFactoryGeneratorService.generateRowIndex();
        
               | foofoo12 wrote:
               | We might be able to use rowIx? Let's discuss it on the
               | next Monday standup. Everyone will need to have an
               | opinion, max 5 minutes per person.
        
         | shiandow wrote:
         | I think the short names aren't anywhere near as bad for
         | readability as using (ri,i) as a table index.
         | 
         | If you're going to use short names at least make it clear which
         | belong together. Especially don't use different lengths when
         | things ought to be similar.
         | data.forEach((row,i) => row.forEach((ele,j) => ... ))
        
         | jfengel wrote:
         | It's the lets that bother me. The point is elderly JS, and the
         | entire operation is fundamentally imperative. But this code is
         | brimming with opportunities to make mistakes. JS deserved its
         | reputation.
        
         | fsckboy wrote:
         | > _Use full words for variable names!_
         | 
         | that's like saying in spoken language "don't ever use pronouns,
         | or even first or nicknames, use full given names"
        
           | groguzt wrote:
           | you are being intentionally dense, they are saying "don't use
           | a single initial to identify someone, use their firstname
           | instead"
        
         | egorfine wrote:
         | > let b = document.body;
         | 
         | This one hurts the most. Save a few bytes for an ungodly amount
         | of mental friction.
        
           | tbrownaw wrote:
           | It doesn't save any bytes, that variable is used _once_.
        
       | Mystery-Machine wrote:
       | The variable naming convention used here could be improved for
       | clarity. I prefer appending `El` to variables that hold DOM
       | elements, as it makes identifiers like `tableEl` clearer and
       | helps avoid ambiguity between variables such as `table` and
       | `row`. Also, the variable named `table` does _not_ actually
       | represent a table element; it would be more accurate to name it
       | `data` or `tableData` to better reflect its purpose.
        
         | embedding-shape wrote:
         | Probably because I first learned programming with JavaScript
         | and very early started using jQuery, but I've always used
         | prefixed `$` to indicate "This is a DOM element" (started doing
         | this once jQuery stopped being so popular). So the example
         | would be something like this for me:                 let table
         | = [         ['one','two','three'],
         | ['four','five','six']       ];       let $body = document.body;
         | let $table = document.createElement('table');
         | $body.appendChild($table);
         | 
         | Always felt it worked out short and sweet, and as long as
         | you're not refactoring a jQuery codebase, seems to work out
         | well in practice.
        
       | pspeter3 wrote:
       | I'm curious what changes the author would like to see to the API
        
       | stared wrote:
       | 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.
        
         | macintux wrote:
         | 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 wrote:
           | I mean, you can just remove all the user agent styles and
           | then <button> is just as stylable as <div>.
        
             | macintux wrote:
             | 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 wrote:
               | 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 wrote:
               | It seems evident to me that semantics are more
               | challenging to define than visuals; it's not the CSS
               | that's the problem.
        
               | lwhi wrote:
               | 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 wrote:
               | 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.
        
         | nonethewiser wrote:
         | 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 wrote:
           | 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.
        
         | art0rz wrote:
         | 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.
        
       | Insanity wrote:
       | Phew, this post single handedly made me feel old this morning. I
       | started dabbling with the web just over 20 years ago but have
       | mainly been working on the backend the past 10-15 years. I had no
       | clue that nowadays programmers don't know about this, so I assume
       | it's supplanted by modern frameworks or modern JS/CSS
        
         | dmd wrote:
         | Same. I use this all the time, have for decades. Had no idea
         | other people didn't.
        
           | zkmon wrote:
           | Just a catchy title. Not abandoned etc. This is the only API
           | available to manipulate HTML table tags.
        
             | jazzypants wrote:
             | Most people use declarative frameworks to build tables, and
             | you could just use `innerHTML` or `append` or any other
             | imperative DOM API to work with tables.
        
               | moritzwarhier wrote:
               | Declarative frameworks build on the imperative DOM API.
        
               | jazzypants wrote:
               | And, not a single one of the declarative frameworks use
               | the HTMLTableElement API!
        
               | zkmon wrote:
               | So how they do they talk to the browser to add a row to
               | the table? Do you know of any API other than DOM used for
               | this?
        
               | plorkyeran wrote:
               | They use createElement instead of the table-specific API.
        
               | simonw wrote:
               | They don't use .insertRow() and .insertCell(). Try
               | searching the React codebase for those.
        
               | zkmon wrote:
               | What do they use?
        
               | simonw wrote:
               | appendChild() and the like.
        
               | moritzwarhier wrote:
               | Yea, but that's pretty much irrelevant as long as the
               | effect is exactly the same. Which brings us back to the
               | point of the article: seeing this and feeling inspired to
               | imagine interface extensions that go beyond syntax sugar.
               | 
               | I was replying to the wrong comment, because I was
               | responding to this:
               | 
               | > I still use this pretty much everywhere to create HTML
               | tables. Do people use something else now?
               | 
               | Regarding React: what would be the benefit for using this
               | old syntax sugar in its vDOM implementation?
               | 
               | Page reflow is not an issue for vDOM as it batches such
               | updates anyway?
               | 
               | And using syntax sugar without benefits in the DOM
               | reconciliation would be pointless.
               | 
               | React also doesn't locate form input elements using
               | document.forms.[name]?.[name] because... why should they?
               | 
               | Just because they can...
               | 
               | Regarding the creation of tables, the most common way to
               | do it would be... parsing initial document's HTML?!
        
             | moritzwarhier wrote:
             | appendChild, replaceChildren, etc work fine with tables?
        
         | alentred wrote:
         | Thank you for confirming I am not... crazy, just old then. I
         | was staring at the code for minutes, trying to spot something
         | unusual that I missed. So, this really just about the `<table>`
         | element, or do I actually not see something?
        
           | paperpunk wrote:
           | It's not about the table element, it's about the API to
           | construct and manipulate that element with a columns and rows
           | interface which is largely superseded by general DOM
           | manipulation.
        
             | littlestymaar wrote:
             | Exactly like how `getElementById` replaced the direct use
             | of the id as a JavaScript identifier.
        
               | xg15 wrote:
               | I remember there being posts that explicitly discouraged
               | using IDs directly, but I'm not sure of tge reasons
               | anymore. Maybe browser incompatibilities or unclear
               | scoping and confusion with other variables?
        
               | withinboredom wrote:
               | It was either Mozilla (Netscape, I think) or IE that it
               | didn't work on for the longest time.
        
               | mook wrote:
               | I think that was a native IE API that Mozilla had to add
               | support for, as well as document.all (Netscape used
               | document.layers).
        
               | chrismorgan wrote:
               | It works everywhere (it's now specified in
               | https://html.spec.whatwg.org/multipage/nav-history-
               | apis.html...), but it's brittle. It can break by adding
               | colliding properties to window deliberately or by
               | accidental global leak (... including things like setting
               | in dev tools), by browser defining new globals, by some
               | 'name' attribute conflict.
        
           | xg15 wrote:
           | It's about the insertRow() and insertCell() methods and
           | rows[] and cells[] fields on the table element, not the table
           | itself.
        
             | eterm wrote:
             | I figured that was the normal way to interact with tables,
             | what would people do otherwise?
        
               | xg15 wrote:
               | Using the standard DOM APIs or - if they don't care about
               | anything - innerHTML, I suppose.
        
               | kleiba wrote:
               | Sorry I - also - am one of those old timers who don't
               | understand this because the shown code is all I've ever
               | used for creating table. So, what is this "standard DOM
               | API" if I may ask? Could you post a code example?
        
               | wging wrote:
               | You can use document.createElement and
               | document.appendChild to create every last <th>, <tr>, and
               | <td> if you want. Those functions are not specific to
               | tables, unlike the one mentioned in the blog post. They
               | can be used to create any elements and place them in the
               | DOM. But if you know what you are doing you can get a
               | perfectly fine table out of that. (Not that you should.)
        
               | xg15 wrote:
               | Yeah, that was what I was thinking of. I knew those as
               | the essential APIs to modify the DOM without a full re-
               | parse. And you can use them on table/th/tr/td nodes just
               | like on any other node.
        
               | thorum wrote:
               | createElement('tr') and table.appendChild(row)
        
         | jcpst wrote:
         | Yep, didn't realize this was unknown by enough web developers
         | to warrant an article.
        
           | embedding-shape wrote:
           | I see new frontend developers using <div> for building
           | buttons, and I've even seen people using <div> for doing
           | titles! Us greybeards don't know how much apparent knowledge
           | we're sitting on, it seems.
        
             | jfengel wrote:
             | Is that bad?
             | 
             | Seems to me that we have redundant mechanisms for
             | specifying semantics: tags and attributes (and classes as a
             | specific attribute). Seems to me that tags are really just
             | syntactic sugar for things like roles. Tables in particular
             | are easily abused.
             | 
             | Of course I use the tag names, because they're idiomatic.
             | But I feel like a newbie who identifies divs as the only
             | true structure builder has a proper developer's intuition
             | for separating presentation from content.
        
               | embedding-shape wrote:
               | > Is that bad?
               | 
               | As long as you think about semantics and accessibility
               | and does the extra work to add those things, then not
               | really.
               | 
               | But why add those extra things when we already get those
               | for free by doing <h1> and then customizing the style?
               | Everything you'd need to manually add, automatically
               | works fine then, so seems like a no-brainer to avoid
               | putting more work on your table.
        
               | swiftcoder wrote:
               | div-as-button/link leaves a lot of default interaction
               | behaviour on the table. You'll need to handle all the
               | keyboard interactions yourself, all the accessibility
               | markup, etc.
        
             | withinboredom wrote:
             | And spans for creating links...
        
               | LaundroMat wrote:
               | Thereby forgetting that some people like to open links in
               | a new tab.
        
               | embedding-shape wrote:
               | And for the ones that remember to implement middle-mouse
               | click to open new tabs, forgets that one can also do
               | CTRL+click to open in new tab, or vice-versa.
               | 
               | Just use <a> please :)
        
               | Izkata wrote:
               | I recently discovered our frontend widget library draws
               | an SVG to implement Radio instead of using <input
               | type="radio">. I was looking at it because they forgot to
               | add a "disabled" attribute.
               | 
               | Best case I'm hoping it's because they were required to
               | get an exact design, but they really should have pushed
               | back on that one if so.
        
             | jacobyoder wrote:
             | In _2004_ I was at a company that dedicated a team of
             | people to rebuilding a bunch of tables (lots of financial
             | data) in to styled divs because...  "tables are
             | depreciated". The fact that they couldn't pronounce or
             | understand the word "deprecated" should have been enough of
             | a clue to ignore this person, but they were the 'lead' on
             | the web team, and... had been there longer than other
             | people. Obviously they must know what they're talking
             | about. Weeks later after having converted dozens of
             | spreadsheets to divs (instead of just using tables) they
             | were 'done', but it was a tremendous waste of time that
             | ignored all the semantics of tables. I was asked to 'help
             | out' on that project to meet the deadline and refused,
             | citing that it was not just stupid, but a big waste of time
             | and against web semantics.
             | 
             | "table" was never deprecated in HTML at all, but was
             | discouraged for general layout (we were aware of this even
             | in the early 2000s). But for representing tabular data -
             | like... data in rows/columns from spreadsheets (with column
             | headers and such)... HTML tables were absolutely the right
             | (only?) way to present this.
             | 
             | I was at that company less than a year...
        
           | bryanrasmussen wrote:
           | I knew it existed but I figured it was only really useful for
           | extremely data-table centric applications so I've never used
           | it.
        
         | prokopton wrote:
         | I've been doing ssr for so long I can't fathom why you'd build
         | a table using JS.
        
           | EvanAnderson wrote:
           | I've been working on a little SPA that manipulates tabular
           | data and allows the user to insert rows. This is exactly the
           | API I've been using. Like a lot of other commenters it never
           | occurred to me that people wouldn't know this API exists.
           | 
           | Aside: I started with Perl CGI scripts, then ColdFusion, and
           | finally Classic ASP back in the 90s. I had a chuckle a couple
           | years ago dealing with a younger developer who was shocked
           | that and oldster like me was up on new-fangled SSR patterns.
        
         | spinningarrow wrote:
         | I've been building sites since around 2000 and I've used HTML
         | tables a lot (including for page layouts, remember those
         | days?). There was a time when I thought I was fluent enough to
         | not have to look up HTML or CSS docs for most things. But I
         | don't think I've ever actively used the DOM API that this
         | article mentions so I learned something new today.
        
           | mattmanser wrote:
           | Surprised, as we used this a lot around 2005, when IE6 was
           | still dominant.
           | 
           | If was much simpler to build tables in javascript with this
           | rather than using document.createElement.
           | 
           | Perhaps this was one of those things that you just had to
           | know about, or be working on data heavy web apps.
        
         | simonw wrote:
         | You knew about the .insertRow() and .insertCell() methods?
        
           | spiderfarmer wrote:
           | I made my first CRUD UI that didn't do full page refreshes
           | with those methods.
        
             | embedding-shape wrote:
             | I think most of us did the ol
             | `$el.appendChild(document.createElement('tr'))` dance
             | rather than using those, at least I did during the 00s for
             | sure.
        
         | phkahler wrote:
         | HTML tables are cognitively if not officially deprecated these
         | days. I made my 1996 resume in HTML using a table for layout
         | and it was indistinguishable from the Word version when
         | printed. Made by editing the HTML by hand too!
         | 
         | Tables are great. I don't doubt that CSS stuff is more capable,
         | but the old ones are still useful.
        
           | xg15 wrote:
           | I think the problem was that tables were always supposed to
           | be for things that look like actual tables in the output -
           | for that purpose they are not deprecated.
           | 
           | What is discouraged is using tables as invisible layout grids
           | - and that was their primary de-facto usecase before CSS and
           | grid layouts. But that had always been a hack, even though a
           | necessary one.
        
             | fortyseven wrote:
             | Yep. Tables for tabular data are still on the menu.
        
             | leptons wrote:
             | Tables are probably still useful for layout in HTML emails
             | (for advertising). I haven't had to work with HTML emails
             | in probably 20 years, but I doubt much has changed about
             | what is and isn't allowed in HTML emails.
        
             | euroderf wrote:
             | > What is discouraged is using tables as invisible layout
             | grids - and that was their primary de-facto usecase before
             | CSS and grid layouts.
             | 
             | After too.
             | 
             | I've seen enough "Introduction to CSS"s filled with caveats
             | and hemming & hawing to know that it's all to be avoided
             | when+if possible. I know, I know, there's a whole wide
             | wonderful world out there full of aligns and borders and
             | containers and insets and margins and masks and offsets and
             | paddings and positions oh my. Bleccch..
        
           | cruffle_duffle wrote:
           | Back in the early to mid 2000's, making your site "table
           | free" while still working on IE6 was seen as a badge of
           | masochistic pride.
           | 
           | Doing table-free multi-column layouts involved doing crazy
           | "float: left/right + padding + margin" with an heavy sprinkle
           | of IE6 clearfix hacks to work right. I mean eventually people
           | dialed in the correct incantations to make table-free designs
           | work for IE6 but it was never quite as straightforward or
           | reliable as a good old fashioned table. Many megajoules of
           | energy were wasted on webform drama between the pragmatic
           | "fuck you, tables just work and I have shit to ship" webdev
           | and the more academic "tables break the semantic web and
           | aren't needed, use CSS." crew.
           | 
           | Like most things, the "tables are evil" mantra was taken too
           | far and people started to use floated divs (or <li/>'s or
           | <span/>'s or whatever) for shit that actually _was_ tablular
           | data! (I was guilty of this!).
           | 
           | And like most things, a lot of the drama went away when IE6
           | finally went away. People who weren't around back then simply
           | cannot understand exactly how much IE6 held back modern web
           | design. You could almost count on half your time being spent
           | making shit work for IE6, despite the ever decreasing amount
           | of traffic it got. I'm pretty sure I almost cried the day
           | Google slapped a "IE6 will no longer be supported" on it's
           | site.... the second they did that, my site got the exact same
           | banner. Fuck IE6. The amount of costs that absolute pile of
           | shit browser caused the industry exceeded the GDP of entire
           | nations.
           | 
           | Anyway.... back to adding weird activex shit in my CSS so IE6
           | can support alpha-blended PNGs....
        
             | icedchai wrote:
             | I remember those days. It was simpler to use tables for
             | layout than to use early CSS for quite a while.
        
           | ranger_danger wrote:
           | > HTML tables are cognitively if not officially deprecated
           | these days.
           | 
           | According to who?
        
         | nunez wrote:
         | I feel like I used this when I built a red-light, green-light
         | dashboard for Windows servers at a bank for my first job out of
         | college (in 2009).
        
         | JofArnold wrote:
         | It's worth checking who the author is... Cristian's not exactly
         | new to the game. I think he's being humble he doesn't know
         | something despite his experience.
        
       | zkmon wrote:
       | Abandoned? When? I still use this pretty much everywhere to
       | create HTML tables. Do people use something else now?
        
         | jckahn wrote:
         | Yes, React
        
           | iammrpayments wrote:
           | Why would anyone use this outdated code over useInsertRow()
           | and useTableColumnEffect()?
        
             | NetMageSCW wrote:
             | What are those and where are they in standard Javascript /
             | DOM API?
        
           | zkmon wrote:
           | 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 wrote:
             | 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 wrote:
               | 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/28fa568972a4d34d867
               | 948...
        
           | embedding-shape wrote:
           | 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 wrote:
             | 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 wrote:
               | > 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 wrote:
               | InsertRow updates the live DOM and React just wholesale
               | replaces it. It's a masterstroke footgun.
        
               | embedding-shape wrote:
               | 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 wrote:
               | Yes that's why of instead of learning the standard apis,
               | you have to spend 15 months learning how to debug
               | useEffect
        
               | embedding-shape wrote:
               | 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 wrote:
           | React is as orthogonal to DOM manipulation API as it is to
           | letting the browser render tables from HTML.
        
         | moritzwarhier wrote:
         | 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 wrote:
         | 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 wrote:
           | 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 wrote:
             | 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.
        
       | smusamashah wrote:
       | 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).
        
       | est wrote:
       | please rediscover html form API
        
       | xg15 wrote:
       | > _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.
        
       | righthand wrote:
       | 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 wrote:
         | 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().
        
       | runarberg wrote:
       | 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.
        
       | psadri wrote:
       | The trouble is not populating it. The trouble is that tables,
       | even though structured semantically, give you absolutely no
       | functionality. There are no search, filter, sort, or selection
       | features that you get.
        
         | qzzi wrote:
         | Compared to what? What gives you all that, and what prevents
         | you from having it with tables?
        
           | kgwxd wrote:
           | countless plugins for use in countless frameworks. We should
           | have all that built-in by now. like we finally have a
           | functioning date picker.
        
           | mcintyre1994 wrote:
           | Javascript arrays have functions for all of that, so if you
           | use something like React and renders your table from data
           | arrays then it's all pretty trivial. I guess the point is
           | that if you have to use JS to do those manipulations, then at
           | some point it's going to be easier to just the
           | React(/Vue/Svelte/etc) approach than manipulating the table
           | yourself using the API described in the article.
        
             | joquarky wrote:
             | Frameworks that make development easy are inherently
             | inefficient. If performance is priority, then you better
             | sort it yourself.
        
       | StrauXX wrote:
       | > 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 wrote:
         | I quickly looked into the webkit code and there's probably
         | absolutely no performance benefit, the same logic should be
         | running behind the scenes
        
       | _the_inflator wrote:
       | Sure!
       | 
       | And there is way more to it.
       | 
       | This kind of code was common and also the starting point of every
       | modern language innovation we have today in JavaScript - even
       | TypeScript, and maybe any modern web development on the server as
       | well.
       | 
       | Tables were the only way to create browser independent layouts
       | dynamically. Or put another way: adding interactivity to
       | websites. And simply because hacking is fun and browsers were
       | experimenting with APIs accessible by JavaScript.
       | 
       | CSS was still bleeding from ACID tests, Netscape was forgotten,
       | Mozilla build Phoenix out of the ashes of the bursting bubble and
       | called their effort Firefox.
       | 
       | In Germany there was and still is the infamous selfHTML project.
       | I remember vividly reading and testing Stefans Munz tutorials on
       | this topic. The content is untouched, only the layout changed, so
       | go back in time for more table fun:
       | 
       | https://wiki.selfhtml.org/wiki/Beispiel:JS-Anwendung-Tabelle...
       | 
       | https://wiki.selfhtml.org/wiki/JavaScript/Tutorials/Tabellen...
       | 
       | It was pretty common to have large one file websites: php and
       | html with css and javascript mixed.
       | 
       | There was no git, no VisualStudio Code, Claude Sonnet - no,
       | Notepad and later Notepad++
       | 
       | (Even the DOOM guys had no version control system in the early
       | stages.)
       | 
       | For me John Resig shines out here. Epic genius behind jQuery. The
       | source code was pure magic, and his book "Secrets of the
       | JavaScript Ninja" is for me the all time climax in programming
       | excellence.
       | 
       | If you never utilised the prototype property, you will never
       | understand any of the most basic structures and inner workings
       | JavaScript has to this day and why Classes are "syntactical
       | sugar" for functions and nothing else.
       | 
       | Function.toString in combination with New Function made me enter
       | 10 matrices in parallel at the time. What a revelation. :D
       | 
       | Nicholas Zakas comes close with his seminal Web Development book,
       | in which he featured every Browser API available at the time with
       | examples on roughly 1000 pages. To this day, exercising most of
       | it and understanding the DOM and Windows object was the best
       | investment ever, because and this fact 15 years later paved the
       | way for the success of a financial SaaS platform. Lost wisdom,
       | not covered by any modern framework like Angular or ReacJS.
        
       | tokioyoyo wrote:
       | Woah, it's always weird to see how there's modern web engineers
       | that didn't grow up during the era where entire layouts were
       | built on tables. Not saying that it was good or bad, but just
       | interesting.
        
         | wombatpm wrote:
         | I remember doing image maps, splitting large images up into
         | pieces, placing them in table cells and adding links to each
         | cell as a poor man's GUI
        
       | The_President wrote:
       | The depreciation of marquee and blink wasn't necessary; it's web
       | developer's choice whether to use these and the visitor's choice
       | whether to be repulsed. Marquee should have been improved for use
       | as ticker elements for specialized application. The depreciation
       | of nobr misses the point - the alternative is more complex. Hope
       | the standard continues to keep the legacy elements: small, i, em,
       | hr... etc.
        
       | chrismorgan wrote:
       | 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 wrote:
         | 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.
        
       | BobbyTables2 wrote:
       | The author didn't know the <TABLE> tag existed ???
        
       | bane wrote:
       | This is a great reminder that the Eternal September still exists
       | and perhaps mercifully appears to be affecting those with at
       | least some technical exposure.
       | 
       | https://en.wikipedia.org/wiki/Eternal_September
        
       | louissan wrote:
       | Hey Chris :-)
        
       ___________________________________________________________________
       (page generated 2025-11-01 23:01 UTC)