The browser certainly makes this convenient... until you have more than a few thousand cells. At some point even just having the whole table loaded into the DOM is too layout and memory intensive (except on servo, sometimes).
When you try, then, to work around those limitations, continuing to use the DOM for it becomes impractical. This gets especially difficult with a spreadsheet, where row and column size is user defined, and thus a scroll offset is a sum of all of those sizes.
I've done this several times, so I eventually settled on a bucketed, run-length encoded cache of row and column sizes, but keeping this data structure current was a mess. The mess further escalated since eventually I worked on an application where the row and column sizes could change in a different chunk with a network update, and that would need to be reconciled somehow.
Another big reason is wasm. It would be a big performance increase to write the layout engine in Rust/wasm. Native performance would be great.
2 easy to write code
github.com/xspreadsheet used table
In general, unless you are doing something very simple, replicating the dom and css engine with canvas is an uphill battle.
That being said, I love that the xterm terminal uses a canvas renderer and now going to move to a webgl renderer. Terminal like UI with monospaced fonts are an excellent candidate for low level rendering.
As an ultimate solution - to remove DOM at all and replace it by <canvas>. Minimization of updates is developer's business in this case. Presumably he/she will be able to do it better other than to walk through all DOM elements while handling, say this:
html:hover span { color:red; }You can style them such a way that updates do not cause re-layout, except for auto-sized cells.