I want to display a large number of columns in html (> 10k Columns and max 200-300 rows) to display a schedule.
The content will be some blocks that are moveable with some text in it and a background color.
Is it possible to display such a large amount of columns with a table/tr/td? Is there a max number of columns or rows that can be displayed with table/tr/td?
Or would you use a canvas? Any other suggestions to solve this?
What is the best way (with great performance when scrolling, ...) to display such a large table?
With this many columns and rows (representing about a minimum of 3,000,000 entries) you will probably avoid filling DOM with those at all cost as any change would trigger reflow which would in this case take a significant amount of time. The number above is also for entries, if each entry takes 100 bytes to represent you are already up at about 280 mb which the browser has to manage.
Normally you would buffer the drawing so only the visible part is drawn/shown on the screen. This means of course you have to implement a custom manager for this. Whether you draw to canvas or use DOM elements sparingly will be up to you.
A challenge with this many columns is to get a scroll bar that is detailed enough to represent a single column, which it likely won't (except from the arrow buttons on the scroll bar), or you would need a very wide screen area to render to.
In addition to this you will also have to consider buffering the data itself by only loading a chunk of it into a buffer. How big that buffer needs to be depends on many factor including connection speed, server, location, data type, browser, scope etc. I would not recommend loading this amount into memory though as it can affect the client system severely resource-wise.
The example given below is just a rough implementation of the rendering principles (buffering) to show what I mean (run it in "Full page" to access the scrollbar intended for the demo):
var ctx = c.getContext("2d"),
rowWidth = 70, // max width of each column
count = Math.ceil(c.width / rowWidth), // number of rows that fit
entries = 10000, // demo
rows = 19,
columns = [];
// Create some dummy columns and row (10,000 x 19)
for(var x = 0; x < entries; x++) {
var row = [];
for(var y = 0; y < rows; y++) row.push(Math.round(Math.random() * 10000));
columns.push(row);
}
// calc scroller size in pixels
document.querySelector("dummy").style.width = (entries * rowWidth) + "px";
// handle updates
document.getElementById("scroll").onscroll = function() {render(+this.scrollLeft)};
// Render rows based on scroller position (rough calcs just for demo)
function render(scrollX) {
var first = Math.floor(scrollX / rowWidth); // first row to display
ctx.clearRect(0,0,c.width,c.height);
// render based on scroller offset and how many rows fit into canvas
for(var x = first, offset = 0; x < first + count; x++, offset += rowWidth) {
if (columns[x]) {
ctx.fillText("Header " + x, offset, 15);
for(var y = 0; y < rows; y++) ctx.fillText(columns[x][y], offset, y * 20 + 35);
}
}
}
render(0); // initial render
#c {background:#ddd}
#scroll {
max-width:700px;
overflow-x:scroll;
height:16px;
}
dummy {display:inline-block}
<div>
<canvas id=c width=700 height=400></canvas>
<div id=scroll><dummy></dummy></div>
</div>