How to avoid the performance cost of overflow:hidden? - html

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.

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]
Put all cell content inside a span element (so can measure offsetWidth of content rather than width of containing block element).
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.
Can skip 1 and 2 above for some columns (if it is known that the cell content will never need clipping).
Caveats:
Measurements only made for iOS5 Safari (I didn't profile any other browser).
Works for us because we dynamically create table rows (processing your example using javascript would be slow?).
Most cells for our data do not overflow (clipping is only required sparsely - only a limited number of cells).
Compromised initial page load (generation of table in page went from 80ms to 800ms).
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.

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.

first off, the amount of markup required to have a table is much larger than just using divs with clear:both css for a new row. so that's the first performance hit.
also, you are setting the overflow as a class ( ? )
<style type="text/css"> .ovfl { overflow:hidden; }</style>
<td class="ovfl"></td>
As an aside, 1000 rows is a weight to deliver.
With divs you at least have an easier opportunity to throw those out of sight ( beyond the scroll ) into a div with display:none until the visitor scrolls to them.
few skins to cat mostly likely on this job,
Hope had some good thoughts.

Webkit bug 75001 is related to this problem and it covers the work being done to solve it (also see bugzilla dependencies for information).

Related

Displaying a lot of text in tables

I have a table, this table gets data from a server, and has a few fields,
The data from the server is plain text, but no limit on how many characters.
The table should not be over 900px wide.
View example
As you can see in my plunker some texts gets very long, so they take several rows, while some fit on the first row.
In my opinion, this is not readable at all, it's horrific.
And here's the real problem, since this should be printed some time, all text must be visible.
I have tried fooling around with some fixed tables and overflow: hidden properties, though this does make the table more attractive, a lot of text would be litterly unreadable
Basically what I am asking is if there are any tried methods for displaying (maybe) a lof of texts in tables, and have it readable?
Edit: Okey, as it seems this is the way to do it, there can be some stylig done, but nothing major. There's is one thing that bothers me though, and that's that the title field (field1) is pushed to the left so much.
I know I can set width, but that requires the table to be fixed, and that will cause problems, I need the table to be as dynamic as possible.
Is it possible to set priortiy on which cells the table will break words on first? So that maybe field 1 and 5 have a low priority, so those cells will be less likely to have line breaks?
The ideal solution, and the solution I have used in most of the projects i've done is to add a modal.
For example, if you have a pragraph of texts, the best thing to do it to display a few words and then add a View more button which will open up a modal which will display the entire paragraph.
You can also try to add a View button in the end of each row in another column. Clicking this would open a modal which shows all the data in that row entirely.
This way you can show some information in the table without making it ugly and also provide all the details in the table itself(although its not present in the table view).
It looks fine to me as well, although you may try alternating row colors... add the following rule to your css... you can of course change the color to whatever you like. I find it improves readability:
tbody tr:nth-child(odd) {
background: #eee;
}

SSRS - Adding empty cells under a tablix to fill empty spaces on the page (if any)

I work with ssrs with a dynamic row data in matrix/tablix. There is possibility when I have more than one page (say it two pages) where the data just fill half of the second page and leave a blank space below (half page blank space on the second page). How is the way to fill this blank space with empty rows? (whether rendering empty rows in the tablix, or inserting background image, or anything. I don't have any solution yet as it is dynamic data with many possibilities of the blank space size on the page)
Unfortunately there aren't any settings in the reporter that support this behavior. There are however several workarounds you could use to get the wanted result.
[1]
You could determine the amount of rows that fit on the first page and on the second page, just in case you have items above the
table on the first page. Before you send the datasource to the
reporter count the total rows and check if it exceeds the first page.
Then calculate the number of rows missing to fill an entire second
page (or third/fourth... if you ever get more data). Finally you add
empty rows/objects at the end of your datasource, which will of cource
cause the pages to be filled to the end.
As was pointed out before, this solution is only possible when working
with fixed row heights. If certain columns can have multi-line cells
then these could be checked as well and taken in account when
calculating the number of rows being displayed on the page. This makes
it slightly more complicated but is still a valid solution if you can
predict which columns might be troublesome.
[2]
A second solution would be to hide the table borders and place the table inside a rectangle that spans the maximum size of the
page. The borders of this rectangle can be used to display the table
outer borders and columns can be displayed by adding lines inside the
rectangle. This will cause the columns to fill the last page of the
report automatically. Unfortunately this isn't a solution to display
horizontal grid lines.
[3]
A third approach is adding an extra table directly below your table
with the same size of columns. Using the same method as from the first
solution you could fill the second table to represent the empty rows.
You'll probably have the same issue as with the first solution when
dealing with multi-line rows though.
I believe solution [1] and [3] will offer the most exact solution, if you're willing to do the math. If you don't want any horizontal lines then I suggest using approach [2].
Using an image to overlay the borders is of course another option but then you'll have the same issues when dealing with the multi-line rows. If you plan on working with fixed row heights, where you leave space for multi-line cells then this is becomes a valid approach but so does solutions [1] and [3].
Update:
If you only need the filled pages for printing you could make sure you add enough empty rows to fill at least the entire last page, these may go to a new page (1 new page, not 2... you can use a simple calculated guess for this) and exclude the last page when printing.

How to position an element on top of another element without using position and margin?

This is my code:
<table>...Some content...</table>
<table>...Another content...</table>
I want to put the second table on top of the first table. This is to be used as an email template (in some clients position and margin are not available).
Those are the only two options available (outside of transform, which definitely won't work if position isn't available) that will allow one element to invade another element's space. If you can't use position or margin, then you're out of luck, and you need to re-evaluate what you are trying to achieve and why. Any chance you could do this with images?
There are always ways...not always elegant, but when you have limited options, 'works' is often all you really need. IMO, creativity is as much about solving a problem with limited options as it is thinking 'outside the box'.
Most email clients allow you to set 'height', so simply wrap the first table (the background) in a div and give that div height:0px;. the table will overflow the div, but the next element won't respect it's space because it has 0 height, and will effectively be layered in front.
http://jsfiddle.net/L0d3tnzu/
If you want the size of the tables to match exactly, you'll probably have to explicitly set heights and widths, but the fiddle above illustrates the basic concept. Hope this helps!
EDIT:
Based on the additional info in the comment (the second table should only partly overlap the first table) here is an updated fiddle: https://jsfiddle.net/acq3ob6y/1/
EDIT #2:
Dang. Outlook switching to the Word/Office rendering engine for HTML/CSS might be the only way possible to get WORSE than the IE version. Sigh. (Thanks to #Gortonington for the comment/clarification, though!)
Ok, then, the idea of a background image is only a problem for retina displays (if you want them to be all crisp and beautiful and retina-ie), and retina devices are going to be handling CSS in a more modern way (hopefully!), so how about this as a solution: Media Query targeting device resolution loads CSS with the double-size img and uses css background-size to constrain it: http://jsfiddle.net/tcyjo7ok
Third try is a charm? At least the list of options is growing...
The only way to overlay two elements across email clients is through use of background images. Even this can be broken in some clients and requires a lot of conditional and reiterate code (backgrounds.cm is good resource for email bg images).
This is the only option that will display in MOST clients. Even this is still very restricted and not very agile to use (but that is true in ALL email coding). Most other techniques will only work for a couple clients and break completely in all others.

Force page break at start of table, if too few lines on first page

I have some tables with print-reapeating thead and many rows. Sometimes a new table starts at the very bottom line of a page, when printing.
I want to force the table to do a page break, if the space left on the page is less than, say 10 cm.
I tried to put an (invisible) overlapping div before that table:
<div style="position:relative;">
<div style="position:abolute; top:0px; width:32px; height:10cm; overflow:visible; page-break-inside: avoid;"> </div>
</div>
<table goes here...>
But it's not working. (FF and IE11)
Is there any way to do that? (I'm trying to print a book, and the table is a new chapter).
I believe this is a bug in Chrome.
The code below demonstrates the best method I've found for multi-page table printing. It has the following features:
column headers repeat on each page
if a page break occurs near the top of the table, it will not leave behind an orphaned set of column headers (a problem which isn't limited to just Chrome)
page breaks occur only between rows
no need to worry about paper size or how many rows will fit-- the browser handles everything automatically
cell borders are always fully closed
the above 3 features apply whether or not the table has headers
works in Chrome!
... and the following known limitations:
doesn't support s (tfeet?)
only supports 1 (which is apparently the most you're allowed to have anyway).
only supports top-aligned
any CSS size values that affect height (including border-width and line-height) must be in px
table cannot (easily) be changed dynamically after the js has run
column widths cannot be set by applying width values to individual table cells; you should either let cell content automatically determine column width, or use s to set specific widths, if needed
I put two tables side by side: the left one (1px) only has a thead with 10cm height, the other contains the contents to print.
That sort of works.
I used float:left; for both tables, so they are side-by-side, but IE11 puts underneath.
Any better idea or an improvment of this approach?

HTML table with raised column effect

I've got a bit of a challenge with an HTML table that we need to have raised columns. If you look at the attached image you'll see what I mean.
The purpose of these raised columns is to draw the user's attention to them.
The problem is:
To get the effect of the column raising above the other columns you
need some kind of element/height/margin to appear outside the
boundary of the table, which doesn't seem to work
Same goes for the bottom
To have the drop shadow appear correctly, it needs to be applied to all the cells in a column.
We did get this to work by splitting it up into multiple tables then applying the styles to the table that should be the raised column. The image I've attached is actually a live table working like this.
But, you loose all other needed features of tables...
Row heights don't match if the text wraps in table 1 but not in
table 2.
To deal with the row height issue we applied a fixed height to each table's rows, but then you have to force text to not wrap. If you then get text that's longer than the width you run into trouble.
Does anyone know how this can be achieved without splitting the tables?
Thanks,
jacques
Try having an extra row for the table above the header row (you may have to stop using any th tags) to give you the overbar at the top. Similarly for the bottom, an extra highlighting row.
Although you have to compromise the table a little to do that, it is better in my book than separating into 2 tables, as that defeats all the purposes of the table tag; to show a table, and have that table easily declared.
The effects inside the table are probably best done with jquery, unless the choice of highlighted columns is entirely static, in which case consider rendering a static html version by generating the html appropriately.