Infinity scrolling

Displaying a lot of data in a grid can be a hazard. The browser can show performance issues when the DOM gets too large. But still we want to present our data to the user in the most friendly way, and it has to look awesome and give a great experience at the same time. Is it possible to have over 1000 rows and 1000 columns in your DOM ready to be scrolled by the user? In this blog post I’m going to show you what the problem is with large data tables, how to fix it with available solutions, and as an alternative I’m going to show the concept of virtualization of data using the CSS grid.

Unwanted behaviour

Let’s create a small application to expose the wound. I’ve created a blank Angular application using the Angular-cli tool. Within this application, I create a table with 100 rows, and 100 columns. The browser doesn’t seem to have any trouble rendering this data, and scrolling through the data goes nice and easy. To get to a point that the browser needs serious time to render the table, I increase the rows and columns to 1000 each. Now the browser needs to work hard to render the table. When I clocked it, it took around 30 seconds to render the table, and I’m unable to scroll fluently through the table.

Check out this plunker to see what happens. If it loads without any issues, try to increase the table rows and columns in app.component.ts.

Solution

This unwanted behavior is caused by adding to much elements to the DOM. To fix it, we need to reduce the DOM size. This can be achieved by virtualization of the data. There are libraries available which make this possible, for example:

Next to these out of the box solutions, I want to share a concept of virtualization and scrolling through this large amount of data by using the CSS grid. In this concept, virtualization on x- and y-axis can be achieved. Positioning of the data will be taken care of by the CSS grid.

Data virtualization with the CSS grid

The unwanted behaviour was exposed by creating a table with 1000 rows and 1000 columns. Instead of positioning the data in a table, I use the CSS grid which positions the data by the CSS properties; grid-column and grid-row. In this example, I create a CSS grid which specifies the size of an implicitly-created grid column, and grid row.

The CSS grid creates columns and rows based on the elements that are positioned within the grid. I add 1 element that spans the entire grid to give the grid a body within the DOM. This provides the container element, which holds the CSS grid, with overflow information in order to scroll.

** The keyword ‘span’ isn’t required, you can also define the span by only using the ‘/’.

The grid is now ready to position the data. For adding the data to the DOM, I define the visible cells by taking the size of the container element and divide it through the column width and the row height used in the grid definition. When calculating the visible cells, I add some buffer cells to make sure the user always sees data.

At this point we have:

  • A CSS grid with a total row and column span where we can scroll through
  • Columns and rows to position the data
  • Elements in the DOM to fill the container with data

When the user scrolls, the data scrolls out of view and the user is left with an empty canvas. To get new data in view for the user, I bind to the scroll event on the container element. When the scroll event triggers, I accomplish to following:

  • Calculate the first visible row based on the scroll offset and the row height
  • Calculate the first visible column based on the scroll offset and the column width
  • Determine whether rows should be moved and update
  • Determine whether columns should be moved and updated

The scroll offset can be used to determine how many data rows and/or columns are scrolled out of view. The data rows and columns that are scrolled out of view need to be replaced with new data.

** I created virtualization for rows, and later I duplicated the code to virtualise the columns as well. This code can be optimised, but for explaining and showing the concept I made it quick and dirty.

All the information is there. The location of the first row that needs to be shown, the first column that needs to be shown, and the total of visible rows and columns. I update the elements within the DOM on 3 points; column index, row index, and data to display.

Conclusion

There are a lot of ways to keep the size of the DOM to a limit to make sure the browser doesn’t get performance issues. Out of the box solutions offer a quick way to make this happen. The concept I’m offering allows you to add 2 dimensional virtualization of data. Only the data and some CSS properties need to be updated during scrolling, which makes it perform fluently and easy to maintain. You can take a large step by clicking on a scroll location within the scrollbar or set the scroll offset through Javascript and the table loads the correct data,  since it is based on an offset location. So if you need a solution where the position of the data is key, the CSS grid with data virtualization is what you are looking for!

That’s all. You can play with the code here.

Tweet about this on TwitterShare on LinkedIn

Reacties

Het e-mailadres wordt niet gepubliceerd.

*