When printing page table rows/cells gets split on page break - css

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.

Related

Cumulative Layout Shift with Bootstrap 4 grid

I am having a problem with high CLS (Content Layout Shift) while using Bootstrap (4.5) grid for two column layout with column order change.
CLS is a Core Web Vital metric. Basically Google sees a problem when webpage's parts are moving when the page is loading. Supposedly this metric is to affect SEO.
On high resolutions my layout consists of two columns. Main content on the right and sidebar on the left. On lower resolutions sidebar content is pushed down below main content. So HTML looks like this:
<div class="container-fluid">
<div class="row">
<div class="col-lg-8 order-lg-2">
</div>
<div class="col-lg-4 order-lg-1">
</div> 
</div> 
</div>
The problem is that for brief moment while the page renders on desktops, the main content appears on the left side, then milliseconds later it shifts to the right place on the right. With simple pages (with simple DOM or no external resources) the shift is not detectable. 
I've prepared an example of such page. (The source code is on github). To measure CLS I am using Lighthouse in Chrome. In my case when I refresh the page I can see columns moving and Lighthouse informs me of CLS value of 0.326. The result might depend on rendering resources so you might get something different. But it seems Google Page Insight gives similar result:
Anyway, is there a way to avoid such shift while the page renders? 
It seems the problem is more Chrome related then flexbox or bootstrap. It turned out that the problem is caused by premature renderation. Chrome's parser "yields" (so it triggers rendering): 
after reading 65536 bytes of data, 
after encountering <script> tag after reading 50 "tokens" (which I think are basically html tags).
The example I provided shows the first case (but actually my real website experiences CLS because the second one). Both of those cases have "bugs" related to them submitted: 1130290 and 1041006. 
So the answer to the problem is hoping that the "bugs" will get resolved. In the meantime depending on actual cause you can limit file size or remove <script> tags.   
 
Short Answer
Minimise the HTML and the problem seems to go away.
Longer Answer
I did a bit of digging, this isn't a complete "this is exactly what happens" answer but I got enough of an idea to come up with the above solution and to roughly explain my reasoning. I am hoping someone can expand upon the gaps in my knowledge.
So what made me come up with the above solution?
After profiling the page load I notice that there were 2 HTML parse tasks being created.
One dealt with lines 1-770 of the HTML and the other dealt with lines 771 to the end of the document.
Because of this the page appears to render the first 770 lines and then recalculates the layout on the second HTML parse task because you have swapped the order (and the .col-lg-4 column is in the second parsing pass HTML).
You won't see this on a "normal" page as if the page is rendered in DOM order layouts will be correct anyway and the second HTML parsing pass will just add more detail to the layout.
As it appeared to be pretty consistent where it cut the page off I removed all line breaks and white space. My theory being that whatever algorithm is deciding where to split the HTML up is using line number as part of that calculation.
By reducing the effective lines to 15 or so I was hoping to make that algorithm only parse the HTML in one pass.
It actually still does it in 2 but the last pass is the closing </html> tag only so doesn't matter. The result of this is when the parsed HTML is combined with the CSSOM it can calculate the layout correctly.
a bit of a hack but it should work up to certain page depths.
please note - if I doubled the DOM node count this workaround did not work again. If I changed the length of each list item (i.e. put lorem ipsum in) but didn't change the structure it did not make a difference. So it appears to be some combination of number of DOM elements and line number that decides when the HTML parser should stop its first pass.
A possible solution
Go back to old layout models. If you use float:left and float:right it should work. I think this specific issue is a combination of page complexity (number of DOM nodes) and using flexbox.
With flexbox being slightly slower than old layout models and sometimes having to use multiple passes (old layout models are single pass) I would imagine this issue would not persist with the above recommendation.
Where I found out about multiple layout passes in certain scenarios

Full iframe path to an element

The application I'm testing is very complex. It has dozens of tabs and thousands of fields. For my tests I need to access ~150 fields.
I'm going through the process of collecting the necessary information to access the elements: xpath, id, css selector, etc. All of these elements sit inside of iframes, sometimes as many as 4 nested iframes. I'm using Firefox to inspect the elements and there is an easy way to get the xpath, css selector, etc. However, in order to figure out what iframe an item is in I have to look through the path in the scrolling bar at the bottom of the inspector window. This is working, my code works, but it's tremendously tedious and has the potential to introduce errors if I miss an iframe.
The question is: is there a way to get the list of iframes that wrap around an element that is easier/faster than the manual investigation that I'm doing now? Possibly something similar to the copy xpath, etc. that is built in to the inspection tool. I'm open to both ideas and applications/extensions.
Once you open the firepath as mentioned in below image :
If you see on top left corner it showing top window, Just click on it, It will show you all the frame present in your web page and once you select any frame then it also show that frams' html as well.
As shown in below image, the frame get highlighted once mouse over on that frame
So here you can easily identify your element is in which frame.
And once you move pointer to the element it will automatically shows that frame as selected where your element is. As shown here.

Ext JS 4: Grid w/ GroupingSummary: print page per group

For an Ext JS 4.1 grid with GroupingSummary, I want to be able to print one page per group.
I am able to get a working solution on Firefox by adding a row after each summary, and setting its #media print style to page-break-before:always. However, this does not work on Chrome or Safari. As I understand it, the reason is that Webkit does not support page-break-before on table rows. I even tried setting the table row display style to block to try to force it, but the page top margins are messed up.
I also was able to get a working solution for all browsers by writing a special printer script, which basically extracts the grid html, clones grid html for each group, and moves each group's table rows to one of these new html grids. Then it takes all the html and writes it to an iframe that covers over the existing web page screen and calls window.print(). One nice thing is that the column headers are at the top of each new group's page.
My main two gripes with this solution are: (1) user can't print original web page using browser print function, i.e., user needs to click on my print button; and (2) it's hacky.
It seems like the best solution would be an Ext-native solution for rendering grouped grids, each its own html table. Does anybody have their own solution that they like?

Internet Explorer, large tables, display:none, CSS

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.

Preventing Page Breaks in a Table When Printing

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.

Resources