Printing HTML table with many columns/rows using CSS layout? - html

I want to print a large table (so large that its rows are approx. 3 sheets of papers wide) from HTML. If possible, CSS should suffice for layout and the solution should work with different browsers.
I'm currently defining the following style rules:
table { page-break-inside:auto; }
tr { page-break-inside:auto; }
When I inspect the DOM elements e.g. in Firefox 33.0.2 (on OS X) I can see that the rules are recognized, but then when I look at a print preview ( File | Print | PDF | Open PDF in Preview) all columns that don't fit on the first page are cut off, i.e. I receive 1 page of printed output instead of 3. I have also tried Internet Explorer 11 and 10 to the same effect.
So how can I layout large HTML tables (ultimately large both in terms of columns an rows) for print out using CSS?
Bonus question: If page-break style components indeed only apply to block-level elements as is indicated in this previous answer, would it help if I construct my table from divs instead of tds when aiming for print output?
UPDATE
Here is a relevant sample that I just tried on JSFiddle. (I don't have an account there, so FWIK I cannot provide a direct link.)
HTML:
<body>
<table>
<tr>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_0</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_1</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_2</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_3</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_4</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_5</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_6</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_7</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_8</td>
<td>The_quick_brown_fox_jumped_over_the_lazy_dog_A_9</td>
</tr>
</table>
</body>
CSS:
table { page-break-inside:auto; }
td { border:1px solid lightgray; }
tr { page-break-inside:auto; }
If I try to print this table (e.g. by applying This Frame | Print Frame ... | PDF | Open PDF in Preview to JSFiddle's Result view in Firefox 33.1 for OS X and for Paper Size/Orientation A4/Portrait) I get one page of output. All columns but the first and part of the second are cut off.

You absolutely need to move away from a table if you need readable vertical printing on the page. Tables are great for display on the page when it's tabular data but are not a viable solution for printing as they don't respect flow.
There are plugins (like this one here, no affiliation – just a Google result) that will do this automatically for you, but here's the example. When you use this, make sure that the #media print is listed appropriately. To test locally, you can change that to #media screen.
That won't show the #page rules listed, but those are visible via a print preview.
Hope this helps:
Fiddle for printing in portrait
HTML
<section class="table">
<div class="row">
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_0</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_1</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_2</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_3</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_4</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_5</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_6</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_7</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_8</div>
<div>The_quick_brown_fox_jumped_over_the_lazy_dog_A_9</div>
</div>
</section>
CSS
#media print {
#page {
margin: 2.5cm;
}
div.row > div {
display: inline-block;
border: solid 1px #ccc;
margin: 0.2cm;
}
div.row {
display: block;
}
}
.table {
display: table;
border-spacing: 2px;
}
.row {
display: table-row;
}
.row > div {
display: table-cell;
border: solid 1px #ccc;
padding: 2px;
}
Edit - Printing horizontally across several pages:
Okay, so this is probably a far less common use case, and we have to do some goofy things with it – so fair warning. I'll try to explain this step-by-step as it's cryptic and obnoxious.
Fiddle for printing in landscape here!
CSS
#media print {
#page {
margin: 0;
}
body {
height: 100%;
width: 100%;
}
div.row > div {
display: inline-block;
border: solid 1px #ccc;
margin: 0.1cm;
font-size: 1rem;
}
div.row {
display: block;
margin: solid 2px black;
margin: 0.2cm 1cm;
font-size: 0;
white-space: nowrap;
}
.table {
transform: translate(8.5in, -100%) rotate(90deg);
transform-origin: bottom left;
display: block;
}
}
This is the part that matters, as it's setting your print directives. Most of this is stuff we've seen in the original (with some tweaks as I was playing with it).
The part we care about comes here:
.table {
transform: translate(8.5in, -100%) rotate(90deg);
transform-origin: bottom left;
display: block;
}
What we're doing is flopping the whole thing on its side, and then sliding it to where we expect it to be. translate(8.5in, -100%) is telling the browser – Slide this element 8.5 inches (the width of a standard letter paper in the US) to the right, and then slide it up 100% of its height (the negative indicates up as opposed to down). We slide it to the right 8.5 inches so that it'll appear at the top of the page when rotated. We slide it up its calculated height so that we don't have an ugly gap to the left of the table when the rotation happens either.
Then, we instruct it that we want all of those calculations run in relation to the bottom left of the element's normal position in document flow. This keeps this crazy long table from being rotated way off to the right by setting the left property. The bottom property is important because we're rotating it clockwise a quarter turn, and if we did that from the top, it would be off the page to the left. That quarter turn is described in the next part of the transform statement: rotate(90deg);
Voila. The thing prints across multiple pages.
Before you ask: No. There is no way to prevent the page break inside the element of which I'm aware. I know it's obnoxious, ugly and all that garbage, but we can only work with the tools which we're given.
Update Firefox confirmed working:

page-break-inside: auto; is the default style, so unless you have a rule setting them differently, those rules will do nothing.
If your table isn't being broken onto multiple pages, then it's most likely because there some other rule you added, which prevents it - my guess an overflow: hidden.
What you first should do is remove all styles, and see if that prints on multiple pages. If yes, start adding your styles back (rule by rule, or if necessary line by line) to find the problem.

If you want to force page break you should use page-break-before or page-break-after. You need to know that the styled element should contain a non-empty block-level element and that it can't be absolutely positioned. However it is quite inconsistent on tables elements. Which leads us to your last question : yes, it would be more consistent to build your tables with divs.
However, considering what you want to achieve (printing large horizontal tables) you should know that trying to fit 3 pages into 1 can't work as your content won't be readable. As a matter of fact, the only best practice would be to use a vertical layout instead (just for print or for both web and print).

Related

A way to have table-rows with height 0 and overflow hidden?

I know it should not be possible, but maybe there's some new quirk... Take a look:
https://jsfiddle.net/1hnxzyux/4/
So I'm using display:table, table-cell and table-row.
I was previously able to get a row to zero height if it doesn't contain anything or if it contains a display:none element, but on the fiddle you can see I've tried to hide the first row/cell by setting height:0 and overflow:hidden on all the elements, including a .box inside the cell, and it really doesn't work.
Please especially test on Safari, because it has some more problems than Firefox and Chrome.
Any way to get rid of the height and hide contents?
EDIT 1: for now, I've found out that IF using a real html table and adding table-layout:fixed to it along with setting some width for it, as for the official specs (and some other posts here in SO) the overflow property does work.
Though, it seems it doesn't work/apply to, css-tables, and I need css-tables.
EDIT 2: Thanks to #zer00ne I updated the fiddle and found that it --would-- work by setting font-size:0 both to td and input field. Though, it's not what I'm currently looking for, since I have to animate the field position and must be fully functional itself. Anyway, these 2 edits can be helpful for other people.
After about one week of searching for a solution, the answer is:
no, it's still not possible. At least, it's not possible in a reliable and versatile way. It's only possible in ways that somewhat limit elements or future actions.
If one doesn't strictly need css-tables (like me in this specific case), you can successfully mimic the same behaviour in 2 ways:
use real tables, apply table-layout:fixed and a width to the table (doesn't matter the unit, can be percentage, for ex.). Than just height:0/oveflow:hidden as usual.
use flexbox. It's the css construct that, with the right rules applied, can better approximate the table behaviour.
Hope it helps
You shouldn't set height of a row. Just place div tag inside each td and put your content in div but not in td directly. The height of row will be equal to height of its content. Set height and overflow for div element and set 0 in top and bottom padding of td. And of course you can use transition for height of div.
$(function() {
$('button').on('click', toggleColumn);
});
function toggleColumn() {
$('div').toggleClass('rollup');
}
table {
border-collapse: collapse;
}
td {
padding-top: 0;
padding-bottom: 0;
border: 1px solid black;
}
div {
background-color: yellow;
height: 40px;
padding-top: 10px;
padding-bottom: 10px;
overflow: hidden;
transition: 2s all;
}
div.rollup {
height: 0;
padding-top: 0;
padding-bottom: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>toggle</button>
<table>
<tr>
<td><div>Column 1</div></td>
<td><div>Column 2</div></td>
<td><div>Column 3</div></td>
<td><div>Column 4</div></td>
</tr>
</table>
If you are simply out after making the first row "invisible", you should simply be able to use CSS's :first-of-type like such:
/* Hide the first occurance of the 'tr' class */
.tr:first-of-type {
display: none;
}
Other than that, I'm not sure why you wouldn't be able to do something like this, alternatively? (a bit like the method you had attempted):
HTML
<div class="tr hidden">
<div class="td">
My Content
</div>
</div>
CSS
.hidden {
display: none;
}
Last but not least, may I ask why you are creating a "handmade" table using div's, instead of HTML's designated table?
You can animate opening a table row with HTML tables using this css:
tr.info td {
transition: all 0.5s ease;
}
tr.info.hide td {
line-height: 0;
padding-top: 0;
padding-bottom: 0;
overflow: hidden;
opacity: 0;
}
Remove the vertical padding which causes the apparent "minimum height" (thanks Andrey Shaforostov). Set opacity 0 to make the text appear as the row grows - smoother effect than using font-size. No need for inner div's - just add/remove the "hide" class on the table row.

Phantomjs apply styling after page breaks

I am generating a PDF Report using phantomjs.
Below is my CSS that avoids splitting text across two pages. It moves the entire line to the new page as expected.
.columns {
page-break-inside:avoid;
}
I wish to insert a margin and border at the beginning of each page, but haven't found a way to apply styling after these page breaks occur. Adding something like below adds the styling I desire to every column class, but I only want it applied to the first occurrence on each page.
#media print {
.columns {
border-top: .1rem solid #f0f1f4;
border-radius: .2rem;
margin-top: 40px;
}
}

Divs refuse to align

I'm fairly new to CSS / HTML, but usually can figure something out. Not with this issue though... I've spent 2 days trying to fix it with no joy
Using WP 3.9.1 and WooThemes Mystile which comes with a custom css to make changes in; no child theme needed. When I place images with captions on a page using left align, some will and others vigorously refuse. In older WP, it was always align all images left to create rows, but not with 3.9.1 it seems. I've tried everything I can think of, but those images that are supposed to be aligned left are actually right of center.
Using Firebug or Safari Inspector, I've tried to align them left and even using a negative margin-left will not place the image where it belongs. It's almost like there's some kind of page break, for lack of a better term, that is making it set right of center. Like it thinks that position is left.
I am not using any gallery or plugin, just adding images to the pages with captions in the text box, not visual. Most of my Galleries under Store are a mess. :(
Here's an example of one: Tuscany Gallery Most of the Galleries I want 2 landscape in a row or 3 verticals. Sometimes with an odd number of images I might center 1 - 3 images, but most are left align.
Any help would be very appreciated! Thanks!
Re: the Body css code
I have a few color changes and more div#attachmet_number (didn't think you needed all them), but this is about it.
:active, :focus {
outline-style: none !important;
-moz-outline-style:none !important;
}
a {
outline-style: none;
-moz-outline-style: none;
}
a:before {
outline: none !important;
}
a:imag {
outline: 0px none;
}
#sidebar .post-46 {
display: none !important;
}
article.post-46 img.alignleft {
margin: 0 1.618em 1em 16px;
}
.post .alignleft, .type-page .alignleft {
margin-bottom: 50px;
}
.post-282 .wp-caption img, .type-page .wp-caption img {
margin: 0 0 0 0.4em;
}
div#attachment_283 {
margin-left: 42px;
}
div#attachment_286 {
margin-left: 42px;
}
div#attachment_291 {
margin-left: 42px;
}
I'm not quite sure if that's what you need or not. The div#attachment_number is the image within a box with caption (title) below it.
HTML of images with caption
[caption id="attachment_516" align="alignleft" width="407"] Duomo di Pisa[/caption]
Following your comments above on your question, your fourth photo (Autumn Drive) specifically is getting pushed to the right by the bottom edge of your second photo (Duomo di Pisa).
It appears that you've added a specific width to each div in your HTML. If you were to add there also a specific, equal height to each div, then they would align and allow the divs below to float to the left.
A greater ideal might be to declare a class for your landscape-oriented divs in your CSS, define a uniform width and height there, and assign that class to all landscape-oriented divs. That way, you could easily change that width and height in one place, and it would apply to all divs with that class assigned (and multiple classes can be assigned to a single div; just separate them by spaces, like class="landscape framed dark" for example).

Create trifold in html/css

I'm trying to create a trifold print out using html/css, but I'm having a devil of a time getting the printed page to come out as I wish.
#page
{
size: 8.5in 11in;
margin: 0;
}
.trifold-segment {
position: relative;
overflow: visible;
width: 2.66in;
padding: 0.5in;
text-align: center;
float: left;
border-right: thin dashed lightGray;
}
.trifold-segment:nth-child(3n+1) {
border-right: none;
}
With this code each trifold segment should be 3.66 inches which should add up to just under 11 inches and fit neatly on an 8.5 inch by 11 inch piece of paper. Instead what I'm finding is that with these dimensions the third segment doesn't fit on the page. I'm not sure what I'm doing wrong or if there is some hidden margin that prevents me from defining the use of the full page myself.
Any insight or links to resources that might help? Thanks!
Most printers by default leave top and bottom and left and right margins when they print. Often there is a way to go full bleed (to the edge) but you'd have to Google your specific printer to find out how. Some printers don't allow this at all, so it all depends on your particular printer.
Cheers!
Cynthia
I ended up creating an RTF document with the properties that I wanted and then dynamically filled it in and offered it up as a trifold download.

expanding Dots pushing link or text down

I created a spanned line with dots to fill in between text of links and phone number, but i cant get it so that if i have to many dots that the text does not go underneath. The problem is on some different brwosers and computers the .... will look fine or it will push it out of the way. How wouldi go about making it so the dots.... would span and the text would not go below the width its supposed to.
<style type="text/css">
#contactInfo {
margin:auto;
width: 480px;
height: auto;
}
</style>
<div id="contactInfo">
<p>Email: .........................................................................info#hereistheemail.com</p>
<p>Phone: ..................................................................................<span class="redBold">888-888-8888</span></p>
</div>
I tried putting less dots buton some browsers it just doesnt look right.
A better way to do what you want is with a definition list. This will semantically present the information you want and not require you to type out a bunch of dots:
HTML
<dl>
<dt>Phone</dt>
<dd>123-4567</dd>
<dt>Email</dt>
<dd>info#email.com</dd>
</dl>
CSS
dl {
/* Adjust as needed. Note that dl width + dt width must not be greater */
width: 300px;
}
dt {
/* The definition term with a dotted background image */
float: left;
clear: right;
width: 100px;
background: url(1-pixel-dot.gif) repeat-x bottom left;
}
dd {
/* The definition description */
float: right;
width: 200px;
}
You can see an example of it here.
You will have to try and create a workaround for this, instead of just using characters.
Some solutions could be using a background image that repeats itself inside some div/span: http://www.htmlforums.com/html-xhtml/t-toc-style-dotted-line-tab-fill-in-html-103639.html
Or you could think of creating a span between the word e-mail and the e-mail address and try to create a border-bottom: dotted 1px black or something equivalent. Or maybe put the information in a table and create one td with that border-bottom.
Another solution would be to check the number of dots needed with some javascript, but this is most certain not robust at all and will not justify-align your content.
So, be creative with a solution. Filling the line with characters is probably not the way to go.
Try this:
#contactInfo {
[ your other styles ]
white-space: nowrap;
}
Another method is with position:absolute
Demo
#contactInfo p
{
position:relative;
}
#contactInfo span,#contactInfo a
{
position:absolute;
right:0px;
}
Edit (cleaned up version)