I have a really big performance issue with Internet Explorer (8 and 9) and large data tables.
When I loaded a few hundred items, the browser (not only Internet Explorer, but also Chrome and Firefox) starts lagging a lot. At first I thought it was because of JavaScript, but later I realized that it was CSS's fault. I found out that with display:none the browser does not render elements, so I made tweaks and started grouping elements in elements and hiding them when they are not visible in viewport like this:
<tbody style="display:none"></tbody>
<tbody></tbody>
Performance did really improve in Chrome and Firefox, but not in Internet Explorer. Internet Explorer seems to still be rendering or trying to recalculate styles for those hidden elements. It looks like display:none makes no difference on Internet Explorer. If I could make not rendering work I believe performance should improve, but I don't know how...
Also the reason why browsers starts lagging with large data table is because each row has about 50 elements inside which are also heavily styled with CSS.
I don't know what else to try to fix this in Internet Explorer...
Any ideas?
P.S.: table-layout is set to fixed
Rendering speed also depends on the way you create elements to the DOM, even though the script itself would be executed fast.
By my (Internet Explorer) experience document.write() is the fastest way to create large tables. It can be over 100 times faster than appendChild(document.createElement()). Also insertRow() & insertCell() are remarkable faster than creating and appending each row and cell. innerHTML seems to be the slowest method to add content (though in this case it can be used to create cell content only, not the table itself).
Unfortunately these differences between performance are not necessarily cross-browser, one browser is doing the same job faster with some other method than another browser...
What can you do then? Try to "split" your table into several smaller tables. You said that table-layout: fixed is set; do you also use COL and/or COLGROUP tags and widths for those? Without them setting table-layout is pretty much useless. Or you could use lazy loading; just load a small part of the table, and when needed, load more.
"Example": I've created an Internet Explorer application, which currently shows 379 tables having six rows with eight cells each. To create and render those tables takes less than 2 seconds (in Internet Explorer 9). However, (I just tested) if I'll create all 2274 rows to a single table, rendering will take about 15 seconds. I assume that splitting the large table to smaller parts would speed up rendering in other browsers too.
Having used display:none on elements that aren't being viewed myself, I can assure you that it is a massive performance gain, even in IE.
The problem you have here is that the browser is constantly having to recalculate column sizes, especiallywhen you change display properties.
To fix, try adding table-layout:fixed to your table's styles. This will effectively disable dynamic column widths and make for more consistent viewing when elements change. You may need to specify widths for your first row, however. This should result in an astronomical performance gain in all browsers.
In order to fix the redrawing issue, use a document fragment. Children appended to the document fragment are not rendered and will not cause the issues you see. You can then insert the fragment itself into the table:
var docFrag = document.createDocumentFragment();
// The following is pseudo code, but you get the picture
for (var i = 0; i < largeCount; i++) {
var row = createRow();
docFrag.appendChild(row);
}
// Append the fragment to the table (or even tbody)
var tbl = document.getElementById('myTbl');
tbl.appendChild(docFrag);
The document fragment itself does not render as anything, it is basically a container element that acts as a placeholder and disappears after you insert it into something.
EDIT: Further information can be found here.
It is actually an issue for all the Internet Explorer browsers without Internet Explorer 11. In general (for all other browsers) 'display:none' means that everything in it shouldn't be really processed from the browser on load, but Internet Explorer does that for some reason.
The only solution is to keep it out of the DOM and render part of the table.
I had the same problem. I initially had one table with 1000 records which was crashing most browsers (Firefox was the only one processing it). And even if it processed the initial DOM, the table was giving that slow dragging sensation (really annoying). So it was kind of unusable.
Then I divided it into smaller tables (200 records) with select drop-down and display:none from the start. This actually completely fixed the issue with the slow page dragging for all browsers. The only problem remained the slow (it takes about 2000 ms) initial load in Internet Explorer 10, 9, 8.
The only way to fix that unfortunately is to specifically exclude the tables from the DOM before load.
I can't see the example code, but you could remove the hidden elements from the DOM.
So instead of just setting display:none, detach them with removeChild() and store them in some object until you need to show them and then insert them at the appropriate place.
Related
I've been using latest Kendo grid for ASP.NET MVC.
Data table specs are like this,
columns --> 25 to 35.
rows --> anywhere between 1500 to 5000.
client side paging --> 20 rows
Issue is, when I'm doing the scrolling, IE 11 takes upto 1s to display data depending on screen resolution and grid content height. Which causes the UI glitch.
When I ran IE UI Responsiveness from Dev Tools, I got the below results.
I get that whenever user does scrolling, browsers have to render the rows and it takes a bit time. But IE 11 takes it to a whole new level. The moment it has to process 3-4 more rows, it starts acting jumpy and glitchy.
I did the testing in Chrome (& opera), Firefox. In which performace was very decent.
I tried to refractor CSS to reduce styling, but there's very little bit change I could afford.
Please let me know what is the next step? Should I keep calm and blame IE?
The grid works fine on its own in IE11, my team uses it.
It could be you've added some code that's being executed excessively.
The UI responsiveness tool isn't very useful. Try using the profiler in IE's Dev tools. Open the page with the problematic grid in it, hit the green arrow of the profiler to start recording, scroll the grid a bit and then hit stop in the profiler.
Sort the results by Count, Inclusive time and Exclusive time and see what stands out. After each sort look at the top ~50 entries for code you wrote.
When sorting by Count, you might find a piece of code that while is pretty short, it runs hundreds of thousands of times in a loop for no reason because of a simple mistake.
Sorting by time can show you pieces of code that are very demanding and perhaps could be moved to other places.
For instance, it could be you're running some logic on the view like formatting a date. If you see such a function in the profiler, it would be better to move this logic to the data fetching phase before the view is rendered.
There's an issue with a file named angular-material.css which causes a slow scroll like you describe. I've seen several places, like this one, that state removing the file or several lines in it solved the problem.
Are you using angular in your project? If you do, see if you have this file and try to remove it.
Because this question crossed 1000 views, I'm obliged to answer on how I fixed my issue.
Turns out, rendering of IE is slow when it comes to bigger screen of HD/FHD resolutions. So, the solution I followed was to promote the grid to new layer by adding the following to grid's CSS class.
.promote-new-layer{
transform: rotate(0deg);
will-change: transform;
}
will-change might not work in all the browsers. Hence the fallback would be to use transform:rotate(0deg).
Please ensure while doing so, you are not promoting unnecessary nodes.
Has anyone ever seen this before, Chrome is calculating my values, even in the body too specifically. Meaning the values are in the millionths if not billions decimals places:
Example:
width: 281.6477355957031px;
I do not have this problem with IE. I normally wouldn't care, but these fractional pixels are really screwing up an effort to add a sticky header to a common grid control we've developed to work with OData.
This issues seems to happen when just a body tag is on the form with no other lower level controls. I am baffled.
Does anyone know of a way to reset the entire html page or even better, just reset a particular element so that every element beneath it calculates using whole or near whole values?
thanks!
EDIT
Just to be clear, I have taken everything off the page except the main container, with no styles and Chrome is calculating this parent html tag, with a value of 1508.1817626953125px. This element has no styles attached
To answer my open question, the cause is Visual Studio 2012. Since I was using localhost to run my site, some plug-in or setting is set to force chrome that specifies dimensions much more specific than any normal human would want. Upon not using machine name instead of localhost the dimensions are back to normal. If i find the exact setting, i will report back later.
EDIT:
Upon further discovery, its not VS, its my browser zooming. At certain zooming in Chrome pixels in the development console are calculated to a sub pixel level. I imagine due to some inner division calculation. This throws off my calculations for allowing the a staic table header at different zoom levels. I will be forced to deal with CSS pixel rounding in my own calculation to handle these.
I have a page that I'm trying to set up for printing. This page contains a large number of individual tables. The tables are of varying size but, in general, I can fit 2.5 to 3 tables on each page. I'd like to be able to prevent the tables from being broken by a page break. Any idea how I can accomplish that?
I tried this:
.reportTable {
page-break-inside: avoid;
}
Unfortunately, page-break-inside only seems to be supported in Opera (according to W3Schools - I verified that this doesn't work in Firefox 4.0.1).
I can do this to force a page break before after every single table:
.reportTable {
page-break-after: always;
}
This works to insert the page breaks and seems to be supported in all major browsers, but it leaves me with tons of wasted space on the printed documents (roughly half of each page is blank). I really only want a page break if the entire next table won't fit on this page.
I know that I have users utilizing Internet Explorer, Firefox, and Safari so I'd really like to support those as much as possible. Finding something that would also work in Chrome and Opera would be a very nice bonus.
Any ideas?
I've also been looking for an answer to this. The closest I came is to knowing approximately how many lines of output would fit on a page, then calculating how many lines of output the page had. In your case:
1) figure out how many lines of output you can fit on a page.
2) keep track of how many lines you've used already by displaying your first table.
3) calculate how many lines table 2 will take. Add it to table 1's lines and see if you're still below your approximate threshold. If you are, display the table, if not, put a div down with the page-break:always in it to force a new table.
This would give you approximately what you are looking for, but it won't be perfect. every once and a while, you'll have a table that "could" have fit on the previous page, but just didn't quite make the cutoff because you have to be on the low side of estimating how many lines fit on a page.
I haven't however figured out a way to facter in if the content inside a cell or something like that will wrap around into a new line when smushed into a printout page.
Hope that sparks an idea for you.
At present, there seems to be no way to force the browsers that don't support page-break-inside: avoid to do so.
However, since you can fit 2.5 to 3 tables on each page and prefer not to print just a single table using page-break-after: always;, you could opt to insert a special div that forces a page break after every two tables.
So you would include <div class="pageBreak"></div> and hide it for the screen but display it for printing. And you would give it a style of page-break-after: always;. In this way, you get at least two tables per page.
Another suggestion would be to let the user decide whether or not he/she wants to print one table per page or as many as can fit (with some possibly being split over the pages). You can toggle a checkbox to add the page-break-after: always; style to the tables.
to fix this just make
#table{page-break-after:auto;}
This is a very old question, so just wanted to update that page-break-inside: avoid; is now supported in most major browsers. Though there are some quirks to making sure page-break-xxx works (NO parent at any level can have position: fixed, the element and direct parent need to be position: relative and display: block, etc.).
Reference:
https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-inside
https://developer.mozilla.org/en-US/docs/Web/CSS/break-inside
Not all printers are created equally.
You are having problems because the printer is not controlled by either the web browser or the html code. It is controlled by the printer driver that came with the printer. This function (and its settings) belongs to the owner of the computer rendering the page, not to you.
Your code can not know in advance how many lines the printer attached to the user's system can put on a page, or how the printer will lay out a table. It will be different if a user with a different printer opens the page. Just like different screen resolutions, there are different printer pixel resolutions.
So all of the rules that apply to different screens (and their disadvantages) also apply to different printers. Not only can't you know where the printer will break a page, you can't even know how large the printed page is, in terms of how much content fits on a page.
To get all of a table (or multiple tables) onto a page, the user should select the parts he wants to print, and then use Print Selection on the printer dialog box.
I have an table with nested tables in. When I am printing this page, the cells gets split on page break.
Is there any chance that I can control that it should jump onto the next page instead of splitting the middle?
I have used the following method to keep the contents of a row together on one page:
<tr style="page-break-inside: avoid">
Unfortunately browser support is limited. Works fine in Internet Explorer 9, but not in Chrome 22 or Firefox 15.
You can have a look at the page-break-before css property. For example you can set it to auto on each of your cells.
Bur I can't guarantee this will work, each navigator prints a little differently. Firefox is known to have problems printing big tables (more than a page) for example.
Does anyone have experience with rendering nested HTML tables? I am attempting to render 30 - 40 rows that each have 5 tables in them. This renders very slowly in Internet Explorer 7 and 8. Is there a trick I can use to speed my table rendering up? Is there a different element I can use other than tables?
if you are working with a nested structure that bad, I would guess that there are ways that it could be refactored to not be as complex, and your performance gain is going to be great by doing so.
However, we would need to see exactly what you are doing to give a valid answer.
30-40 tables is a lot of code to render. You should definitely switch to CSS layouts.
Setting explicit height and width on every element in the tables will improve browser layout performance.
For internet explorer, see http://msdn.microsoft.com/en-us/library/ms531161(VS.85).aspx
Setting the property to fixed significantly improves table rendering speed, particularly for longer tables.
Setting row height further improves rendering speed, again enabling the browser's parser to begin rendering the row without examining the content of each cell in the row to determine row height.
Tables are good for grids of information. For most other applications use a styled unordered list UL.
Add:
table
{
table-layout: fixed;
}
Be aware: some text may flow out of the table cells now.