Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid the performance cost of overflow:hidden?

I have an HTML table that can be more than 1K rows and a dozen or so columns.

I want the columns to be a fixed size (controllable by the user) and not grow/shrink either vertically or horizontally. So visually the contents of a particular table cell will be on one line and the overflow gets cut off at the end of the cell.

Doing performance analysis in Chrome on a large table the main performance killer is overflow:hidden.

I've tried putting the contents of each cell inside of an input, since that would replicate the same visual behavior, but that has a similar performance impact.

What do people recommend to improve performance?

If necessary I don't have to use a table tag, but would prefer to stick with the table tag if good performance can be achieved.

Update 1: I've included a file that demonstrates the performance issue here. Warning the file is pretty massive (25MB) and will slow down your computer. By default the table does not have overflow set to hidden, and once the table has been loaded (can take a while) the browser performance relatively smoothly.

However, if you edit the file and uncomment lines 12-15 and then open it. You'll see after loading browser around the table is significantly less responsive.

like image 287
Omar Ismail Avatar asked May 15 '12 22:05

Omar Ismail


People also ask

What happens if we use overflow hidden?

hidden - The overflow is clipped, and the rest of the content will be invisible. scroll - The overflow is clipped, and a scrollbar is added to see the rest of the content. auto - Similar to scroll , but it adds scrollbars only when necessary.

What is the purpose of the hidden value in the overflow property?

The hidden value of the overflow property hides all the content that is exceeding the box area. This property should be handled with care because the content that this property hide is completely invisible to the user, however, it is best suited for displaying content that is dynamic in nature.

What is overflow hidden mean?

Set Overflow to hidden to prevent unwanted horizontal scrolling and extra whitespace in your project when elements exist outside the viewport.


2 Answers

FYI: I have run into this problem on the iPad/iOS causing performance problems with a page that has about a hundred rows in a table with table-layout:fixed.

As soon as a cell, or a div in a cell, gets an attribute that forces it the cell to be drawn individually, it takes about 300ms instead of 100ms to draw (which causes the UI to feel abysmally slow for my situation).

Either of two properties (position:relative or overflow:hidden) caused the problem for me, removing them optimised the speed but caused text overflow if cell text was too wide for the fixed width columns.

The slowdown was happening even after tables were drawn, because I am dynamically popping up an absolute div over the table. When profiling the javascript (using (new Date).getTime()), the slowdown in measured in places in the javascript that have nothing to do with the table.

[edit: added following as part solution]

  1. Put all cell content inside a span element (so can measure offsetWidth of content rather than width of containing block element).
  2. After appending the row into the document, test if each span.offsetWidth is greater than the column width, if so add the "overflow:hidden" to the style (or via a class) of the containing block.
  3. Can skip 1 and 2 above for some columns (if it is known that the cell content will never need clipping).

Caveats:

  1. Measurements only made for iOS5 Safari (I didn't profile any other browser).
  2. Works for us because we dynamically create table rows (processing your example using javascript would be slow?).
  3. Most cells for our data do not overflow (clipping is only required sparsely - only a limited number of cells).
  4. Compromised initial page load (generation of table in page went from 80ms to 800ms).
  5. But sped up dynamic combo popup (340ms down to 130ms) giving much better keyboard responsiveness.

For your situation, might be fast to first using variable width columns, measure offsetWidth of all columns, setting column widths to pixel widths and setting overflow:hidden only on columns where offsetWidth of column is greater than the pixel width you will be using for the column.

like image 169
robocat Avatar answered Oct 14 '22 04:10

robocat


You could try using a tiled approach. It is a pretty typical approach to making things like infinitely side-scrollable games efficiently.

Put all of your data into a Javascript array, and then have N + 1 rows in a table that has N rows visible. When you scroll down, the last item would move into view. At the moment that you have scrolled far enough that the first item moves out of view, you shift all of the data up a row and reset the scroll position back to where it started. Done correctly, the shift would be completely transparent to the user. You would only ever be working with N + 1 rows in an N-rows-visible table.

I've done this before, but under very specific UI constraints. I kind of shutter at the thought of making this consistent using the built-in browser scrollbars and such.

like image 31
Chris Zacharias Avatar answered Oct 14 '22 03:10

Chris Zacharias