How to style tables on successive pages of a paged media output? - css

I have an html table like this:
<div class="report">
<table>
<thead>...</thead>
<tfoot>...</tfoot>
<tbody>
<tr class="row-to-style">...</tr>
</tbody>
<tbody>...</tbody>
</table>
</div>
Note that all tbody's above are identically structured. I want to style the very first tr.row-to-style row differently from the others. Each tbody will have a tr.row-to-style but I want to only affect the first such row on a page. The output is paged media, specifically PrinceXML produced pdf files from xhtml source files. This means we can use advanced css selectors, cross-browser compatibility is not required, and javascript cannot be used.
It's easy enough to style the target row on the first page of output. I can use:
table tfoot + tbody tr.row-to-style {...}
Also, if I know how many tbody's will fit on a page, I can do something like:
table tbody:nth-of-type(4n+1) tr.row-to-style {...}
But if I don't know the number of tbody's that will fit on a page, how can I target the first one?
On output, in effect, the thead and tfoot sections are repeated for each page. The tables were designed this way specifically to take advantage of this. We allow for page breaks after a tbody. The output may contain several pages.
Thus, the output has sort of a pseudo-thead and pseudo-tfoot on each page. But I see no way of using such to mark the first tbody on a page. Any ideas? Thanks...

There just doesn't seem to be any documentation that talks about the possibility of targeting css based off the "page box" that the #page creates. Everything talks about how the #page creates a "page box" but nothing about how to access or point to that page box for styling of child elements on a page. These are all shots in the dark, untested, and likely not valid, but maybe...
#page tbody:first-child tr.row-to-style { styles go here }
Or perhaps some use of named pages? Like:
#page nameOfPage {}
tbody:first-child tr.row-to-style {page: nameOfPage; other styles go here}
Or something like #media defining:
#page {
tbody:first-child tr.row-to-style { styles go here}
}
Or maybe (since I assume the content is generated on each page for thead and tfoot, which should theoretically place thead before the first tbody of each page):
thead + tbody tr.row-to-style { styles go here }
Honestly, I don't expect any of these to work, but you can give them a try. The problem seems to be that the real tfoot is only defined once at the top of the source and therefore the css selectors do not recognize the page generated one's as existing for styling purposes.

Related

CSS Selector for first-child after a page break

How can I style the first-child AFTER a page break has occurred?
The ultimate situation I'm facing is that I would like to style the first row of a table differently, and when printing the table spans multiple pages. I successfully used :first-child to style the first row. I also successfully avoided page breaks inside rows. I can not figure out how to style the first row on the second page of the table, though.
I'm familiar with the css pseudo class first-child (http://www.w3schools.com/cssref/sel_firstchild.asp), and I'm also familiar with the css print property page-break-inside (http://www.w3schools.com/cssref/pr_print_pagebi.asp). I'm unable to get them to play nicely together?
EDIT:
Adding code sample
HTML:
<table>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</table>
CSS:
table tr:first-child td { border-top: solid red 2px; }
table tr { page-break-inside: avoid }
Okey, direct answer — you can not do that as how you want.
Edit: oh, looks like I answer for a little more complicated question like "how to add table header on each printed page", but, anyway the way of solution is the same. Hope it's ok.
But there is several tricks to do what you want.
1) Break table in several parts, add thead part to each of them and remove margin, so it will looks like just one table. Add in css something like:
table {
page-break-inside: avoid;
page-break-after: auto;
}
table + table thead {
display: none;
}
Also do not forget to set td width, cause tables without thead can have different width's.
After that add print styles:
#media print {
table + table thead {
display: table-column-group;
}
}
Yep, there is a chance for duplicate headers on page, but it still better than nothing. And if you find good number of lines for your project it will looks as you need
2) Prepare dedicated downloaded printable version of page with WKHTMLTOPDF, for example. So you can catch page breaks well, and add what you need. This option give max flexibility of output, but will take some time for support.
3) Calculate everything with JS. Print your page and analyze it — add some constants to js (height per page), and, when someone try to print — calculate page breaks, find closest element and add what you need.
Hope you got answer.
Have a nice day.
I was also looking for a way to apply styles to only the first and last rows of a table over a page break, but maybe for a different use case.
I needed to give my whole table a border, but not on the table rows, just the outside. The easy way is to add a border to the table, but when a page break occurs, the borders aren't redrawn at the break.
My solution was to use a thead and tfoot, as these elements are repeated at every break. This gave me a full border around the table that obeyed page breaks.
You can modify this technique for your circumstances. Say if you wanted to change the styles of just the first row (and have it be consistent across page breaks), you just put that row in the thead or the tfoot depending on if you want the first or last row. You can even do this with an existing thead. Just give each thead tr a class so you know which is the main header, and which is a styled row.
There were a few caveats. The table footer had to have something within its tds otherwise it won't render. I added a (which means "no breaking space") to the first td and then set the font-size on the td to 1px (Otherwise there will be a noticeable gap at the bottom of your table). The font size has to be applied directly to the td. A font size of 0 will not work either. It has to be non-zero.
Example
This example is for my use case, but you can modify it. You can also use as many columns as you want. I used one for simplicity. The thead and tfoot must have the same number of columns though.
.my-table tr {border-left: 1px; border-right: 1px;}
.my-table thead {border-top: 1px;}
.my-table tfoot {border-bottom: 1px;}
// must be applied to the td!!!
.my-table tfoot td {font-size: 1px;}
<table class="my-table">
<thead><td></td></thead>
<tbody>
<tr><td>data</td></tr>
<tr><td>data</td></tr>
</tbody>
<tfoot><td> </td></tfoot>
</table>

Hide a Span title from a th scope tag

I have to hide part of a table, the cells are th tags and inside the th I have Span title. I been looking but I can't find any tip. I would like to hide one of the cells, in sort of just hiding one cell of the the entire table. Its possible to perform this with the CSS file?
This is how my css is made:
.GridHeaderStyle th{text-align:center;}
.GridMainSytle td, .GridHeaderStyle th
{
border:thin solid #ffffff;
*border:none;
}
As you can see the th and td are together and I can not really just specify the th in question. Google developper tools show me that the th tag is as
<th scope="col" widgth="10%">
<span title="column1">
I have tried the follow but it hide me all the cells and not the one in question.
.GridHeaderStyle th[scope=col]
{
display:none;
}
Thanks in advance
Please try below CSS code :
.GridHeaderStyle th span {
display:none;
}
Without seeing more of the markup, it's hard to know for sure, but it's likely based on the example that the th[scope=col] selector matches all of your header cells. Look at using the nth-child CSS selector to be more specific, but be aware that's a brittle solution. If your markup changes such that the header you wish to suppress is now in a different order, your rule will hide the wrong column.
If your use case allows it, you could hide the span rather than the column, and therefore address the element a bit more specifically. Try the rule:
th span[title=column1] {
display:none;
}

Print a header for every page in Google Chrome

I'm creating a TV schedule and it shouldn't have any print problems for at least one standard browser.
I need to put logo and title plus table headers on every page, after days of trying and searching I found out that Chrome wouldn't print table headers and position: fixed elements on every page because of this known bug.
Because of the capabilities such as printing background colors with -webkit-print-color-adjust: exact which I've heavily used and changing page borders with CSS #page property, I've customized my view to use Google Chrome, but now that I see it cannot print headers I'm looking for an alternatives which are:
To forget Chrome and start creating print view for another browser which needs to do tweaks to print background colors and change page margins (I'm afraid it's not possible).
To find a CSS/JS solution to make Google chrome to print table headers on every page.
TL; DR: Do you know any jQuery/JavaScript/etc. code to print table headers on every page in Chrome?
Yep, that's a Webkit/Chrome thing.
It won't print the thead on each page. FF for instance does.
What you could do to achieve something like this is use page-break.
Page break does only work on block elements, so you should style your tr's accordingly.
Like this:
tr{
display:block;
}
Now, you should start copying your thead and put it in at every Xth row with javascript:
var head = $('table thead tr');
$( "tbody tr:nth-child(10n+10)" ).after(head.clone());
On screen, you don't want all those heads. Remove them with a media query this (for convenience I added a .head class on my th > tr row.:
#media screen {
tbody .head{
display: none;
}
}
Now before each .head make the page break:
tbody tr.head {
page-break-before: always;
page-break-inside: avoid;
}
Check it out overhere: http://jsfiddle.net/jaap/7ZGVv/2/
Keep in mind, jsfiddle doesn't allow you to open just the preview frame, so printing does not work overhere, combine everything in your own file and you'll see the tables will split up, styling is not perfect, and it's not as flexible as your browser itself deciding where to split, but hey, it's something.
I have posted a solution here that solves this problem and does not require you to try to preempt the natural page breaks with forced page breaks (a technique which is inherently unreliable and tends to waste paper).
This solution won't work exactly for table headers, but it will allow headers of arbitrary html. I've created a library that allows Chrome to print headers and footers, see this answer.

Avoid css styles applying to child elements

Is there any way that parent tag styles do not apply to child tag elements?
I have to display some data so I wish to align them in table for better view. I want to apply some styles to the table to make it look good. I am using some additional components (like plugins) in my table. So if I do apply any style to tr tag of my table, those are applied to those components tags too, if they have tr tag. This should not happen...
Is there any way that I can avoid inheritance?
<style>
/*The plug-in component may have table tr tags.So the following styles should be applied to plug-in..*/
table tr{
background:#434334;
border-radius:5px;
}
</style>
CSS are meant to be inherited like that. If you want to "not inherit" you have a few options:
Best: improve your selectors so that they only apply to the elements you need them to
Good: if existing markup does not allow you to do the above, help by giving the element(s) that need to be styled an additional attribute (e.g. extra class) that allows you to improve the selectors
Bad: write your selectors so that they apply globally, then write more selectors to "undo" the results on a case by case basis
In your case, it looks like a combination of the first two would work. You can give an id="foo" to your table and then change the selector to
table#foo > tbody > tr { /*...*/ }
The > is the child selector, which prevents the style from being applied to table rows further down the element tree.
One solution would be to name your style table tr.style1{ ... and then in each of your <tr>'s you could just add a class attribute, i.e. <tr class="style1">.

Is it necessary to have <tbody> in every table?

Is it necessary to have <tbody> in every table? According to Standards.
Only if you define thead and tfoot. It is mostly used when the table has multiple bodies of content. If the data in the table is easily understood to be the tbody then you can safely omit it.
Quoting the HTML 4 spec: "The TBODY start tag is always required except when the table contains only one table body and no table head or foot sections. The TBODY end tag may always be safely omitted."
So, you must have a <tbody> tag if you have a <thead> or <tfoot>
See also: MDN
For the small fraction of your users still using IE7, you MUST add encapsulate your tr's in a tbody tag if you're building a table with the DOM methods!
This will work in all major browsers:
var table = document.createElement('table');
var tbody = document.createElement('tbody');
var tr = document.createElement('tr');
tbody.appendChild(tr);
table.appendChild(tbody);
This will NOT work in IE7:
var table = document.createElement('table');
var tr = document.createElement('tr');
table.appendChild(tr);
A quick blog post of mine on building tables:
http://blog.svidgen.com/2012/05/building-tables-in-ie7-with-javascript.html
It may be notable that I no longer make the effort to support IE7 on my own projects. The IE<=7 share is likely negligible for most sites at this point.
Dumb Guy gave an answer for HTML4 (yes). Arwym gives an answer for HTML5 to a related question (no):
The tabular data spec for
HTML5
does not require them:
Contexts in which this element (tr) can be used:
As a child of a thead element.
As a child of a tbody element.
As a child of a tfoot element.
As a child of a table element, after any caption, colgroup, and thead elements, but only if there are no tbody
elements that are children of the table element.
Even though I believe it is a good practice to section your rows
within thead, tbody and tfoot tags as it makes the table's rows
easier to identify.
In the end, the browser will always add at least the tbody for you.
According to HTML 3.2 spec (table wasn't in HTML 2 spec) table element doesn't have tbody, thead, tfoot (they are HTML 4 things), only optional caption and list of tr / th.
While you might think what's the hell you are talking about HTML 3.2 dated 1997 in 2021 consider email clients with primitive or outdated HTML engines, tbody makes no sense in here.
Most browsers are forgiving but even so I add the pair in all tables that I use now. Even trivial tables. Especially now that I'm using CSS more and more to decorate those tables.
All that being said I have old tables that still work fine on the newest browsers. I'm learning the hard way but taking the few extra Micro seconds to add the optional tags here and there ends up saving you money/time in the long run.
Dave

Resources