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
Related
This is my first post and I don't know how to structure the code any differently.
First off everything displays fine and if I have 22 different ids it would validate fine too.
In my table, the column is styled by nth child to align everything centre.
If I class the TD, then the class gets overridden by the TR nth child
So I have currently this HTML
<td colspan="2" id="statsdiv">Total of Houses..</td>
And this CSS
#statsdiv {text-align:right;}
.table1861 tr td:first-child {
text-align:center;
}
I have 355 rows in the table, and 22 need to be aligned to the right hand side. Surely I don't need to have the same ID with 22 different suffixes
Thank you
Like Harry mentioned in the comments
The rule
.table1861 tr td:first-child {
text-align:center;
}
will never overwrite
#statsdiv {text-align:right;}
Cause the ID is a more specific identifier. More details on CSS specificity can be found here
So probably you didn't show all the IDs and classes in your example thats why you might really face the problem you are saying in your question.
To answer the other part of your question though: Yes just adding a class instead of an id like:
<td colspan="2" class="align-right">Total of Houses..</td>
should work:
.table1861 tr td.align-right {text-align:right;}
But you might want to have a look at calculating a selector's specificity to not run into any issues
Change your ID to a class, and then in your css for the class use the !important selector after you align right, this will make it take priority.
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>
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;
}
My boss wants me to stop using CSS layouts and start using table layouts. A major factor in this is the desirable behavior of tables in horizontally positioned, fluid layouts. See this example:
http://jsfiddle.net/CXSS2/2/
If you slide the width of the HTML panel narrower, you will see that the table (the first one) has several convenient qualities:
Automatically finds a good place to split the two cells, giving the cell with more content a larger percentage of the available width.
Fills all of the available width 100%.
When deciding which of the cells to wrap, it does so in the way most efficient with regards to vertical space.
Keeps the two cells aligned horizontally no matter what.
Example A does not have quality 1. (You have to update the ratio by hand if the content size changes.)
Example B does not have quality 1 or 3. (Static 50% is less than ideal but could work. However, it breaks on to 3 lines while the table is still only 2 lines tall.)
Example C does not have quality 2 or 4. (I can see ways to fake quality 2 with this one, but clearing down to the next line is totally a deal breaker.)
Example D does not have quality 1 or 4. (Technically it has 1, but the huge gap in between is not practical. Also, left/right floating on the same line doesn't work well in some browsers.)
Since the data is not semantically tabular, I really want to avoid using tables. But my boss pays me, so I need to go with what he says or find a better solution. Is there a way to do this using semantic markup and CSS?
Updated: For all browsers > ie7 you can use display: table, table-row, table-cell. the jQuery code will target ie7 and then replace the div's with appropriate table elements.
If this is the only problem you've run into so far, you shouldn't install some goofy grid system just to fix this. That's overkill and a waste of time.
http://jsfiddle.net/CoryDanielson/yuNTX/
sample html
<div class="table width100pct"> <!-- .table should have NO style. just 'display: table' -->
<div class="tr">
<div class="td"></div>
<div class="td"></div>
</div>
</div>
<!-- class="table, tr, td" is ONLY for changing display: table, table-row and table-cell.
you SHOULD NOT include any styles inside of these CSS selectors. These classes will
be removed when the divs are transformed into <table>, <tr>, <td>
-->
//conditionally load the javascript patches for ie7
<!--[if IE 7]><script src="/js/IE7fixes.js"></script><![endif]-->
IE7fixes.js
$(document).ready(function(){
//comment out the if statement to check functionality without ie7
if ($.browser.msie && $.browser.version == 7) {
$('html').addClass('ie7') //<html class="ie7">.. like modernizr
var elem, elemClass
$('div.table').each(function(i, elem) {
elem = $(elem)
elemClass = elem.removeClass('table').attr('class') || ''
elem.wrapInner("<table class='" + elemClass + "' />").children().unwrap()
})
$('div.tr').each(function(i, elem) {
elem = $(elem)
elemClass = elem.removeClass('tr').attr('class') || ''
elem.wrapInner("<tr class='" + elemClass + "' />").children().unwrap()
})
$('div.td').each(function(i, elem) {
elem = $(elem)
elemClass = elem.removeClass('td').attr('class') || ''
elem.wrapInner("<td class='" + elemClass + "' />").children().unwrap()
})
}
});
You should structure your CSS similar to mine
required css
table, div.table { width: 100%; }
tr, div.tr { vertical-align: top; }
/* the following 3 classes will be dropped when transformed in ie7
but that won't matter because they'll fall back to <table><td><tr>
*/
div.table { display: table; } /* NO STYLES HERE */
div.tr { display: table-row; } /* NO STYLES HERE */
div.td { display: table-cell; } /* NO STYLES HERE */
I haven't used tables for laying out non-tabular content of a website for years so I might be missing a few things here but I have some alternatives and ideas.
To abstract it some: It sounds like the root issue is that your boss wants you to use a web development technique that is faster than the one you are currently using, allows you to achieve the same layout, and he isn't concerned with semantic markup.
I think a CSS or site building framework like Twitter Bootstrap or 960gs (Note: 960gs is included in Bootstrap) could be used to achieve the same goals instead of a table based layout. These frameworks do have some non-semantic markup such as div's to contain the rows and span's to set the width and offset elements but are better than using a table with regards to accessability and the amount of non-semantic markup.
You can additionally mitigate this by giving your elements ids and additional classes and styling them, and there is less non-semantic markup than if you used a table based layout.
Going off my interpretation of the root issue, a framework like either of these also gives you pre-styled elements and a way of nicely spacing out elements that will save you time in the overall design -> code -> revise cycle and none of this goes against web development best practices.
Some resources for Twitter Bootstrap:
http://twitter.github.com/bootstrap/ - Has the download and good documentation
http://twitter.github.com/bootstrap/scaffolding.html - Examples of the code you would use in Bootstrap instead of a table based layout
960gs (960px wide Grid System):
960.gs/ - Homepage
https://speakerdeck.com/u/nathansmith/p/960-grid-system - The definitive 960gs tutorial and reasons on why to use it
http://sixrevisions.com/web_design/the-960-grid-system-made-easy/ - The tutorial I first used to learn about grid systems in web design
If I got my initial assumption wrong, sorry! Also if you have any questions or want more information let me know.
Have you given a shot to css frameworks such as foundation? It beats having td within a td within a table within a td within a table ... (:
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.