Usable Table (Table Parser) - Web Experience Toolkit (WET)
Table related element
I classify all the table related element into two category:
- Structural element:
- table
- colgroup
- col
- thead
- tbody
- tfoot
- tr
- Informatif element:
- caption
- td
- th
The usable table are defined by it's informatif element and supported/extended by it's structural element. Also, this document define a table to be an unique rowgroup with a caption element as it's cell header. The objective are not to talk about the accessibility WCAG 2.0 related to table. All the above concept are ignoring any attribute like "scope" and "id/headers" because they are there for accessibility purpose and may can not represent the visual perceptible strucutre of the table.
Why the attribute like "scope" and "id/headers" are ignored ? Simply because in a upcomming time, I would build a plugin able to detect all the cell relationship and set, when appropriate, the value for "scope" and "id/headers" attribute. That will only work if this guide about how to design an usable table are followed.
General Table Layout
This is a correct layout
Colgroup | Colgroup | ||||
Layout Cell | Column header | Column header | Column header | Column header | Column header |
---|---|---|---|---|---|
Row group header (Level 1) | |||||
Row group header (Level 2) | |||||
Row header (Level 3) | 66 | 64 | 20 | 87% | 0 |
Row header (Level 3) | 34 | 31 | 20 | 84% | 0 |
Row header (Level 3) | 36 | 36 | 42 | 92% | 0 |
Row header (Level 3) | 19 | 23 | 66 | 96% | 0 |
Row Group header (Level 2) | |||||
Row header (Level 3) | 297 | 297 | 66 | 84% | 1 |
Row header (Level 3) | 396 | 381 | 67 | 88% | 3 |
Row header (Level 3) | 422 | 437 | 111 | 93% | 1 |
Row header (Level 3) | 626 | 654 | 99 | 99% | 0 |
Row Group header (Level 1) | |||||
Row Group header (Level 2) | |||||
Row header (Level 3) | 12 | 11 | 11 | 100% | 0 |
Row header (Level 3) | 0 | 0 | n/a | n/a | 0 |
Row header (Level 3) | 3 | 4 | 17 | 100% | 0 |
Row header (Level 3) | 8 | 8 | 33 | 100% | 0 |
Row Group header (Level 2) | |||||
Row header (Level 3) | 89 | 99 | 50 | 96% | 0 |
Row header (Level 3) | 1 | 2 | 46 | 50% | 0 |
Row header (Level 3) | 107 | 104 | 64 | 97% | 0 |
Row header (Level 3) | 527 | 599 | 66 | 98% | 0 |
But this one not
The recommandation would be at the second section to move it to a new table or swap the first row group with the second row group at level 1. (See the row group level identifier)
A Data table need to be consistant, Also the first row group header set would establish the subsequent structure. Alway have the most general information at the top of the table and go to more specific when you go down in the table.
Colgroup | Colgroup | ||||
Layout Cell | Column header | Column header | Column header | Column header | Column header |
---|---|---|---|---|---|
Row group header (Level 1) | |||||
Row group header (Level 2) | |||||
Row header (Level 3) | 66 | 64 | 20 | 87% | 0 |
Row header (Level 3) | 34 | 31 | 20 | 84% | 0 |
Row header (Level 3) | 36 | 36 | 42 | 92% | 0 |
Row header (Level 3) | 19 | 23 | 66 | 96% | 0 |
Row Group header (Level 2) | |||||
Row header (Level 3) | 297 | 297 | 66 | 84% | 1 |
Row header (Level 3) | 396 | 381 | 67 | 88% | 3 |
Row header (Level 3) | 422 | 437 | 111 | 93% | 1 |
Row header (Level 3) | 626 | 654 | 99 | 99% | 0 |
Row Group header (Level 1) | |||||
Row header (Level 2) | 12 | 11 | 11 | 100% | 0 |
Row header (Level 2) | 0 | 0 | n/a | n/a | 0 |
Row header (Level 2) | 3 | 4 | 17 | 100% | 0 |
Row header (Level 2) | 8 | 8 | 33 | 100% | 0 |
Row header (Level 2) | 89 | 99 | 50 | 96% | 0 |
Row header (Level 2) | 1 | 2 | 46 | 50% | 0 |
Row header (Level 2) | 107 | 104 | 64 | 97% | 0 |
Row header (Level 2) | 527 | 599 | 66 | 98% | 0 |
Recommanded
Colgroup | Colgroup | ||||
Layout Cell | Column header | Column header | Column header | Column header | Column header |
---|---|---|---|---|---|
Row Group header (Level 1) | |||||
Row header (Level 2) | 12 | 11 | 11 | 100% | 0 |
Row header (Level 2) | 0 | 0 | n/a | n/a | 0 |
Row header (Level 2) | 3 | 4 | 17 | 100% | 0 |
Row header (Level 2) | 8 | 8 | 33 | 100% | 0 |
Row header (Level 2) | 89 | 99 | 50 | 96% | 0 |
Row header (Level 2) | 1 | 2 | 46 | 50% | 0 |
Row header (Level 2) | 107 | 104 | 64 | 97% | 0 |
Row header (Level 2) | 527 | 599 | 66 | 98% | 0 |
Row group header (Level 1) | |||||
Row group header (Level 2) | |||||
Row header (Level 3) | 66 | 64 | 20 | 87% | 0 |
Row header (Level 3) | 34 | 31 | 20 | 84% | 0 |
Row header (Level 3) | 36 | 36 | 42 | 92% | 0 |
Row header (Level 3) | 19 | 23 | 66 | 96% | 0 |
Row Group header (Level 2) | |||||
Row header (Level 3) | 297 | 297 | 66 | 84% | 1 |
Row header (Level 3) | 396 | 381 | 67 | 88% | 3 |
Row header (Level 3) | 422 | 437 | 111 | 93% | 1 |
Row header (Level 3) | 626 | 654 | 99 | 99% | 0 |
OR
Colgroup | Colgroup | ||||
Layout Cell | Column header | Column header | Column header | Column header | Column header |
---|---|---|---|---|---|
Row group header (Level 1) | |||||
Row group header (Level 2) | |||||
Row header (Level 3) | 66 | 64 | 20 | 87% | 0 |
Row header (Level 3) | 34 | 31 | 20 | 84% | 0 |
Row header (Level 3) | 36 | 36 | 42 | 92% | 0 |
Row header (Level 3) | 19 | 23 | 66 | 96% | 0 |
Row Group header (Level 2) | |||||
Row header (Level 3) | 297 | 297 | 66 | 84% | 1 |
Row header (Level 3) | 396 | 381 | 67 | 88% | 3 |
Row header (Level 3) | 422 | 437 | 111 | 93% | 1 |
Row header (Level 3) | 626 | 654 | 99 | 99% | 0 |
Colgroup | Colgroup | ||||
Layout Cell | Column header | Column header | Column header | Column header | Column header |
---|---|---|---|---|---|
Row Group header (Level 1) | |||||
Row header (Level 2) | 12 | 11 | 11 | 100% | 0 |
Row header (Level 2) | 0 | 0 | n/a | n/a | 0 |
Row header (Level 2) | 3 | 4 | 17 | 100% | 0 |
Row header (Level 2) | 8 | 8 | 33 | 100% | 0 |
Row header (Level 2) | 89 | 99 | 50 | 96% | 0 |
Row header (Level 2) | 1 | 2 | 46 | 50% | 0 |
Row header (Level 2) | 107 | 104 | 64 | 97% | 0 |
Row header (Level 2) | 527 | 599 | 66 | 98% | 0 |
OR
Colgroup | Colgroup | |||||
Layout Cell | Column header | Column header | Column header | Column header | Column header | |
---|---|---|---|---|---|---|
Row group header (Level 1) | ||||||
Row group header (Level 2) | Row header (Level 3) | 66 | 64 | 20 | 87% | 0 |
Row header (Level 3) | 34 | 31 | 20 | 84% | 0 | |
Row header (Level 3) | 36 | 36 | 42 | 92% | 0 | |
Row header (Level 3) | 19 | 23 | 66 | 96% | 0 | |
Row Group header (Level 2) | Row header (Level 3) | 297 | 297 | 66 | 84% | 1 |
Row header (Level 3) | 396 | 381 | 67 | 88% | 3 | |
Row header (Level 3) | 422 | 437 | 111 | 93% | 1 | |
Row header (Level 3) | 626 | 654 | 99 | 99% | 0 | |
Row Group header (Level 1) | ||||||
Row header (Level 2) | 12 | 11 | 11 | 100% | 0 | |
Row header (Level 2) | 0 | 0 | n/a | n/a | 0 | |
Row header (Level 2) | 3 | 4 | 17 | 100% | 0 | |
Row header (Level 2) | 8 | 8 | 33 | 100% | 0 | |
Row header (Level 2) | 89 | 99 | 50 | 96% | 0 | |
Row header (Level 2) | 1 | 2 | 46 | 50% | 0 | |
Row header (Level 2) | 107 | 104 | 64 | 97% | 0 | |
Row header (Level 2) | 527 | 599 | 66 | 98% | 0 |
Having a summary group
Rowgroup summary
That is about having a "Total" and/or "Subtotal" row. It's called "rowgroup summary". Rowgroup because it can contain more than one row and Summary because that information is directly related to the previous rowgroup.
Example:
Filed | Granted | |
---|---|---|
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
Total | 4477 | 1980 |
In the previous exemple, It can make sense to group the "Total" row inside a "tfoot" rowgroup element because "tfoot" element it's defined as column summary.
The biggest question about tfoot will be: How do you define column summary?
- Is "column summary" means "table footnote for additional information regarding some table cell" ?
Use the technique to add a description to a cell discussed in a topic bellow.
- Is "column summary" means "additional column information (like a description)" ?
Use the technique to add a description to a cell discussed in a topic bellow.
- Is "column summary" means "data column summary" ?
Seem fine, but came unrelevant when there are more than one data rowgroup if each of them have a sub rowgroup summary (like a sub-total row).
- Is "column summary" means "data rowgroup summary" ?
For me, that are the best definition. This will allow to use data rowgroup (tbody) to illustrate the summary data. When tfoot rowgroup are used with this definition, that would say the summary data are applicable for every data rowgroup in the table.
When data are added in the tfoot rowgroup, that will represent either the summary of each data rowgroup or the summary of each summary rowgroup but not both.
Please note that the "tfoot" rowgroup can be rendered in three possible way. Those render method are given to the user agent.
- Rendered as other tbody rowgroup but with an visual representation (line a larger border at the top of it's first row set in CSS)
- Rendered to support scrolling of body sections. (see HTML4 - 11.1 Introduction to tables - 3rd Paragraph)
- Rendered to be printed on each pages at the bottom of an table (see HTML4 - 11.1 Introduction to tables - 3rd Paragraph)
Be careful before to use it. Ask you the question if you would like to have your summary data row in the tfoot rowgroup be rendered in all those three possible way. If your answer is "No", I would recommand to to use an unique/separated "tbody" to represent your data row summary.
Sub Rowgroup summary
In the next table, you will see a table with one data rowgroup, one sub rowgroup summary and one total. Please note, this is only possible when the sub rowgroup summary have 2 or more data row.
Filed | Granted | |
---|---|---|
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
Sub Total | 4477 | 1980 |
Foreign Countries | 30841 | 17798 |
Total | 35318 | 19779 |
In the next table, you have two set of data rowgroup, two set of data rowgroup summary of one row each and a big total at the end
Filed | Granted | |
---|---|---|
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
Sub Total | 4477 | 1980 |
Foreign Countries | ||
Danish | 746 | 400 |
German | 409 | 144 |
Japan | 106 | 42 |
Korean | 26 | 13 |
Finland | 16 | 6 |
Spanish | 1 | 0 |
United States | 53 | 21 |
United Kingdom | 2122 | 884 |
Sub Total | 4477 | 1980 |
Total | 35318 | 19779 |
FYI - in the previous table, the "Foreign Countries" rowgroup will be considerated as a sub rowgroup of the one with all the province.
Next example are with 2 paralel data rowgroup
Filed | Granted | |
---|---|---|
Canada | ||
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
Sub Total | 4477 | 1980 |
Foreign Countries | ||
Danish | 746 | 400 |
German | 409 | 144 |
Japan | 106 | 42 |
Korean | 26 | 13 |
Finland | 16 | 6 |
Spanish | 1 | 0 |
United States | 53 | 21 |
United Kingdom | 2122 | 884 |
Sub Total | 4477 | 1980 |
Total | 35318 | 19779 |
Colgroup summary
A Side Note: A colgroup can be defined to only include the row heading cell (th) similar to the thead tag. Whatever a colgroup can have in his scope row header mixed with data cell. The final decision regarding this will be the designer / editor depending of it's needs or his internal guideline. The consequence is when a colgroup contains data cell mixed with row header would be simply imposible to swap the row with the column and can be resulted finally into serveral smaller usable table.
A colgroup summary can be cleary defined visually when there are two or more rows assigned in the column header in the row group section (thead). That wont required you to have set the colgroup tag previously but still recommended to have. The other way to define is the colgroup tag. That are very useful when there are only one row in the column header in the row group section (thead).
Colgroup summary with one row of column heading
<colgroup /> <colgroup span="2" /> <colgroup />
Filed | Granted | Total | |
---|---|---|---|
Alberta | 746 | 400 | 1147 |
British Columbia | 409 | 144 | 658 |
Manitoba | 106 | 42 | 150 |
New Brunswick | 26 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 |
Northwest territories | 1 | 0 | 1 |
Nova Scotia | 53 | 21 | 74 |
Ontario | 2122 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 |
Quebec | 871 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 |
With a sub column group containing two row or more
<colgroup /> <colgroup span="2" /> <colgroup span="2" /> <colgroup />
Filed | Granted | Sub Total | Examined | Total | |
---|---|---|---|---|---|
Alberta | 746 | 400 | 1147 | 400 | 1147 |
British Columbia | 409 | 144 | 658 | 144 | 658 |
Manitoba | 106 | 42 | 150 | 42 | 150 |
New Brunswick | 26 | 13 | 30 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 | 48 | 68 |
Northwest territories | 1 | 0 | 1 | 6 | 20 |
Nova Scotia | 53 | 21 | 74 | 21 | 74 |
Ontario | 2122 | 884 | 3025 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 | 10 | 17 |
Quebec | 871 | 408 | 1279 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 | 62 | 182 |
Colgroup summary with two row of column heading
[recommend but optional] <colgroup /> <colgroup span="2" /> <colgroup />
Application | Total | ||
---|---|---|---|
Filed | Granted | ||
Alberta | 746 | 400 | 1147 |
British Columbia | 409 | 144 | 658 |
Manitoba | 106 | 42 | 150 |
New Brunswick | 26 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 |
Northwest territories | 1 | 0 | 1 |
Nova Scotia | 53 | 21 | 74 |
Ontario | 2122 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 |
Quebec | 871 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 |
With a sub column group containing tow row or more
[required] <colgroup /> <colgroup span="2" /> <colgroup span="2" /> <colgroup />
Application | Sub Total | Examined | Total | ||
---|---|---|---|---|---|
Filed | Granted | ||||
Alberta | 746 | 400 | 1147 | 400 | 1147 |
British Columbia | 409 | 144 | 658 | 144 | 658 |
Manitoba | 106 | 42 | 150 | 42 | 150 |
New Brunswick | 26 | 13 | 30 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 | 48 | 68 |
Northwest territories | 1 | 0 | 1 | 6 | 20 |
Nova Scotia | 53 | 21 | 74 | 21 | 74 |
Ontario | 2122 | 884 | 3025 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 | 10 | 17 |
Quebec | 871 | 408 | 1279 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 | 62 | 182 |
Two sub column group containing two row or more.
[required] <colgroup /> <colgroup span="2" /> <colgroup /> <colgroup span="2" /> <colgroup /> <colgroup />
Filed | Granted | Sub Total | Operational Application | Total | |||
---|---|---|---|---|---|---|---|
Searched | Examined | Sub Total | |||||
Alberta | 746 | 400 | 1147 | 400 | 1147 | 400 | 1147 |
British Columbia | 409 | 144 | 658 | 144 | 658 | 144 | 658 |
Manitoba | 106 | 42 | 150 | 42 | 150 | 42 | 150 |
New Brunswick | 26 | 13 | 30 | 13 | 30 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 | 48 | 68 | 48 | 68 |
Northwest territories | 1 | 0 | 1 | 6 | 20 | 6 | 20 |
Nova Scotia | 53 | 21 | 74 | 21 | 74 | 21 | 74 |
Ontario | 2122 | 884 | 3025 | 884 | 3025 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 | 10 | 17 | 10 | 17 |
Quebec | 871 | 408 | 1279 | 408 | 1279 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 | 62 | 182 | 62 | 182 |
FYI - in the previous table, the "Operational Application" column group will be considerated as a sub column group of the second colgroup defined (see they are spanned in two row).
Two paralel column group containing each a column group summary.
[required] <colgroup /> <colgroup span="2" /> <colgroup /> <colgroup span="2" /> <colgroup /> <colgroup />
In/Out Office Application | Operational Application | Total | |||||
---|---|---|---|---|---|---|---|
Filed | Granted | Sub Total | Searched | Examined | Sub Total | ||
Alberta | 746 | 400 | 1147 | 400 | 1147 | 400 | 1147 |
British Columbia | 409 | 144 | 658 | 144 | 658 | 144 | 658 |
Manitoba | 106 | 42 | 150 | 42 | 150 | 42 | 150 |
New Brunswick | 26 | 13 | 30 | 13 | 30 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 | 48 | 68 | 48 | 68 |
Northwest territories | 1 | 0 | 1 | 6 | 20 | 6 | 20 |
Nova Scotia | 53 | 21 | 74 | 21 | 74 | 21 | 74 |
Ontario | 2122 | 884 | 3025 | 884 | 3025 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 | 10 | 17 | 10 | 17 |
Quebec | 871 | 408 | 1279 | 408 | 1279 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 | 62 | 182 | 62 | 182 |
Rowgroup summary with an colgroup summary
Since I create HTML table I never had to design a table like this. But we never know, may be someone somewhere need or will need to design a table with column group summary and row group summary togheter. You will see here how to do it and what happen with the cell at the coordinate of each group summary.
The particularity here is about the coordinate cell at the intersection between the column group summary and the row group summary. They can be layout cell (empty td element) or the summary of the summary (td element with data). But it's not acceptable for that intersection to be set as a cell header (th element)
In the next example, the intersection of group summary are layout cell and they are empty. Also the data at intersection between the summary colgroup and the global table summary (named here row and column Total) can be a data cell or a cell used for layout. They are layout cell in the example.
[required] <colgroup /> <colgroup span="2" /> <colgroup /> <colgroup span="2" /> <colgroup /> <colgroup />
In/Out Office Application | Operational Application | Total | |||||
---|---|---|---|---|---|---|---|
Filed | Granted | Sub Total | Searched | Examined | Sub Total | ||
Canada | |||||||
Alberta | 746 | 400 | 1147 | 400 | 1147 | 400 | 1147 |
British Columbia | 409 | 144 | 658 | 144 | 658 | 144 | 658 |
Manitoba | 106 | 42 | 150 | 42 | 150 | 42 | 150 |
New Brunswick | 26 | 13 | 30 | 13 | 30 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 | 48 | 68 | 48 | 68 |
Northwest territories | 1 | 0 | 1 | 6 | 20 | 6 | 20 |
Nova Scotia | 53 | 21 | 74 | 21 | 74 | 21 | 74 |
Ontario | 2122 | 884 | 3025 | 884 | 3025 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 | 10 | 17 | 10 | 17 |
Quebec | 871 | 408 | 1279 | 408 | 1279 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 | 62 | 182 | 62 | 182 |
Sub Total | 4477 | 1980 | 4477 | 1980 | |||
Foreign Countries | |||||||
Alberta | 746 | 400 | 1147 | 400 | 1147 | 400 | 1147 |
British Columbia | 409 | 144 | 658 | 144 | 658 | 144 | 658 |
Manitoba | 106 | 42 | 150 | 42 | 150 | 42 | 150 |
New Brunswick | 26 | 13 | 30 | 13 | 30 | 13 | 30 |
Newfoundland and Labrador | 16 | 6 | 20 | 48 | 68 | 48 | 68 |
Northwest territories | 1 | 0 | 1 | 6 | 20 | 6 | 20 |
Nova Scotia | 53 | 21 | 74 | 21 | 74 | 21 | 74 |
Ontario | 2122 | 884 | 3025 | 884 | 3025 | 884 | 3025 |
Prince Edward Island | 7 | 0 | 7 | 10 | 17 | 10 | 17 |
Quebec | 871 | 408 | 1279 | 408 | 1279 | 408 | 1279 |
Saskatchewan | 120 | 62 | 182 | 62 | 182 | 62 | 182 |
Sub Total | 4477 | 1980 | 4477 | 1980 | 25687 | ||
Total | 35318 | 19779 | 35318 | 19779 |
Indented row header
Sometime I already see a table that the rowgroup header are combined with the summary column. Something like the following table.
Filed | Granted | |
---|---|---|
Canada | 4477 | 1980 |
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
The visual relation between the "Canada" header and the following "Provincial" header is perceptible for a visual person and perceptible for a screen reader if the "Canada" header have a scope attribute set to "rowgroup". But what is for somebody that are using a custom style sheet or if no style sheet are used at all ? You can get something like the following table.
Filed | Granted | |
---|---|---|
Canada | 4477 | 1980 |
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
Now the relation between the "Canada" header and the "Province" header are not visible. But if you have set the attribute scope to rowgroup, the screen reader will now have advantage over the graphical user agent. I can imagine somebody saying, yeah but that would be perceptible for an graphical user agent without style sheet if we transform that table by adding a layout cell before each "Province". As the following example:
Filed | Granted | ||
---|---|---|---|
Canada | 4477 | 1980 | |
Alberta | 746 | 400 | |
British Columbia | 409 | 144 | |
Manitoba | 106 | 42 | |
New Brunswick | 26 | 13 | |
Newfoundland and Labrador | 16 | 6 | |
Northwest territories | 1 | 0 | |
Nova Scotia | 53 | 21 | |
Ontario | 2122 | 884 | |
Prince Edward Island | 7 | 0 | |
Quebec | 871 | 408 | |
Saskatchewan | 120 | 62 |
That is true, if there are layout cell before each "Province" now everybody can see the relation. But in a data table my recommandation is to avoid the use of layout cell for padding purpose. For me the only layout cell that can be authorized in a data table is a cell at a dead spot. I define the dead spot by the intersection of a column and a row where there relation are not reliable for the user. For exemple the intersection between the colgroup header and the rowgroup header (absolute top left cell), a cell in the intersection of a colgroup summary and a rowgroup summary as explained before.
Decorative cell should be avoided at anytime. Here you have the same data structure but the data cell assigned to the rowgroup was moved into a rowgroup summary with a row named Total.
Filed | Granted | |
---|---|---|
Canada | ||
Alberta | 746 | 400 |
British Columbia | 409 | 144 |
Manitoba | 106 | 42 |
New Brunswick | 26 | 13 |
Newfoundland and Labrador | 16 | 6 |
Northwest territories | 1 | 0 |
Nova Scotia | 53 | 21 |
Ontario | 2122 | 884 |
Prince Edward Island | 7 | 0 |
Quebec | 871 | 408 |
Saskatchewan | 120 | 62 |
Total | 4477 | 1980 |
Use data cell for layout
Inside a data table, a cell can not be used for layout purpose. The exception are the summary/header group intersection if they are empty cell. Also in general a layout cell will be represented by td element but the top left cell can be a th element. The intersection between data group, data row and data col will be a data cell. In some case a data cell will be empty or contain something like "N/A". The meaning of that particular cell will be an absence of data and not a layout cell.
Bad example (with layout data cell)
There is an HTML comment after each layout data cell.
ID | Measurement | Average | Maximum |
---|---|---|---|
Cats | |||
93 | Legs | 3.5 | 4 |
10 | Tails | 1 | 1 |
English speakers | |||
32 | Legs | 2.67 | 4 |
35 | Tails | 0.33 | 1 |
Source Code
<table>
<thead>
<tr>
<th>ID</th>
<th>Measurement</th>
<th>Average</th>
<th>Maximum</th>
</tr>
</thead>
<tbody>
<tr>
<td></td> <!-- Layout data cell -->
<th scope="rowgroup">Cats</th>
<td></td> <!-- Layout data cell -->
<td></td> <!-- Layout data cell -->
</tr>
<tr>
<td>93</td>
<th>Legs</th>
<td>3.5</td>
<td>4</td>
</tr>
<tr>
<td>10</td>
<th>Tails</th>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td></td> <!-- Layout data cell -->
<th scope="rowgroup">English speakers</th>
<td></td> <!-- Layout data cell -->
<td></td> <!-- Layout data cell -->
</tr>
<tr>
<td>32</td>
<th>Legs</th>
<td>2.67</td>
<td>4</td>
</tr>
<tr>
<td>35</td>
<th>Tails</th>
<td>0.33</td>
<td>1</td>
</tr>
</tbody>
</table>
Good design (without a layout data cell)
ID | Measurement | Average | Maximum |
---|---|---|---|
Cats | |||
93 | Legs | 3.5 | 4 |
10 | Tails | 1 | 1 |
English speakers | |||
32 | Legs | 2.67 | 4 |
35 | Tails | 0.33 | 1 |
Source Code
<table class="lined">
<thead>
<tr>
<th>ID</th>
<th>Measurement</th>
<th>Average</th>
<th>Maximum</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="4">Cats</th>
</tr>
<tr>
<td>93</td>
<th>Legs</th>
<td>3.5</td>
<td>4</td>
</tr>
<tr>
<td>10</td>
<th>Tails</th>
<td>1</td>
<td>1</td>
</tr>
<tr>
<th colspan="4">English speakers</th>
</tr>
<tr>
<td>32</td>
<th>Legs</th>
<td>2.67</td>
<td>4</td>
</tr>
<tr>
<td>35</td>
<th>Tails</th>
<td>0.33</td>
<td>1</td>
</tr>
</tbody>
</table>
Row Type
There are 2 types of row that can be found inside a data table.
- Row Header
- Data row
Row header
A row header are identified by it's last cell. The last cell must be an cell header (th). There are 2 kind of row header that are acceptable in a data table. The most usable one are an row header only composed of cell header (th). That include any spanned cell that would cross the row header. The second type of row header, only allowed in a data table, is only applicable to the first row "table tr:first" starting at the first column in a data table. It's allowed to define a data cell (td) at the position. That cell will be considerated to be a layout cell for the purpose to annonce where, not limited to, the data row heading will be located into the data table. The same effect can be done by defining an empty cell header (<th></th>) at the same position (top left corner in the table).
Valid Example
Perfect row header
Cell Header | Cell Header | Cell Header | Cell Header |
---|
Source Code
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | |||
---|---|---|---|---|
Cell Header | Cell Header | Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="2">Cell Header</th>
<th colspan="4">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Cell Header |
Source Code
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<th colspan="4">Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | Cell Header | |
---|---|---|---|
Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="2">Cell Header</th>
<th colspan="2">Cell Header</th>
<th rowspan="2">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Row header with a layout cell
Note: This case are only applicable to the top left cell in the table scope.
Cell Header | Cell Header | Cell Header |
---|
Source Code
<table>
<tr>
<td></td>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | Cell Header |
---|
Source Code
<table>
<tr>
<th></th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | ||||
---|---|---|---|---|
Cell Header | Cell Header | Cell Header | Cell Header |
Source Code
<table>
<tr>
<td rowspan="2"></td>
<th colspan="4">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | ||||
---|---|---|---|---|
Cell Header | Cell Header | Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="2"></th>
<th colspan="4">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | Cell Header | |
---|---|---|---|
Cell Header |
Source Code
<table>
<tr>
<td></td>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<th colspan="4">Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | Cell Header | |
---|---|---|---|
Cell Header |
Source Code
<table>
<tr>
<th></th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<th colspan="4">Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | ||
---|---|---|---|
Cell Header | Cell Header |
Source Code
<table>
<tr>
<td rowspan="2"></td>
<th colspan="2">Cell Header</th>
<th rowspan="2">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | ||
---|---|---|---|
Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="2"></th>
<th colspan="2">Cell Header</th>
<th rowspan="2">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Not a valid row headers
Invalid because the second row finish with a cell heading
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Data Cell | Data Cell | Data Cell | Cell Header |
Source Code
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<td>Cell Header</td>
<td>Cell Header</td>
<td>Cell Header</td>
<th>Cell Header</th>
</tr>
</table>
Invalid because there are a data row between 2 headers
Cell Header | Data Cell | Cell Header | Data Cell |
---|
Source Code
<table>
<tr>
<th>Cell Header</th>
<td>Data Cell</td>
<th>Cell Header</th>
<td>Data Cell</td>
</tr>
</table>
Invalid because there are a data row between 2 headers and the row end with a cell header
Cell Header | Data Cell | Cell Header | Cell Header |
---|
Source Code
<table>
<tr>
<th>Cell Header</th>
<td>Data Cell</td>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Invalid because the second row have an layout cell in it's first column
Cell Header | |||
---|---|---|---|
Cell Header | Cell Header | Cell Header | |
Cell Header | Data Cell | Data Cell | Data Cell |
Source Code
<table>
<tr>
<th>Cell Header</th>
<td>Data Cell</td>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Don't use the first table row for the caption
If the first row of the table are spanned into the full width of an table. That won't represent an group heading but will be more a table caption. If that sequence are repeated in the table, it recommanded to split your table in 2 or more table.
Bad Example
Cell Header [2] | |||
---|---|---|---|
Cell Header [3] | Cell Header [4] | Cell Header [5] | Cell Header [6] |
Data Cell [7] | Data Cell [8] | Data Cell [9] | Data Cell [10] |
Source Code
<table>
<caption>Here is an table caption [1]</caption>
<tr>
<th colspan="4">Cell Header [2]</th>
</tr>
<tr>
<th>Cell Header [3]</th>
<th>Cell Header [4]</th>
<th>Cell Header [5]</th>
<th>Cell Header [6]</th>
</tr>
<tr>
<td>Data Cell [7]</td>
<td>Data Cell [8]</td>
<td>Data Cell [9]</td>
<td>Data Cell [10]</td>
</tr>
</table>
Recommended
Here is an table caption [1]
Cell Header [3] | Cell Header [4] | Cell Header [5] | Cell Header [6] |
---|---|---|---|
Data Cell [7] | Data Cell [8] | Data Cell [9] | Data Cell [10] |
Source Code
<p>Here is an table caption [1]</p>
<table>
<caption>Cell Header [2]</caption>
<tr>
<th>Cell Header [3]</th>
<th>Cell Header [4]</th>
<th>Cell Header [5]</th>
<th>Cell Header [6]</th>
</tr>
<tr>
<td>Data Cell [7]</td>
<td>Data Cell [8]</td>
<td>Data Cell [9]</td>
<td>Data Cell [10]</td>
</tr>
</table>
Having a second column heading set
If in your table, after one data row was followed the table column set, you should not have a second column heading set. Having a full width row header after any data row are allowed. If you have set a second column heading set, this is represented by having paralel cell header, you can move that block into a second table or remove it if the purpose is to repeat the first column heading.
Invalid
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Cell Header | Cell Header | Cell Header | Cell Header |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Source Code
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
</table>
Recommanded
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Source Code
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
</table>
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
</table>
OR
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Data Cell | Data Cell | Data Cell | Data Cell |
Source Code
<table>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
<tr>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
<td>Data Cell</td>
</tr>
</table>
Column heading structure
The column heading, when they are build from serveral row, need to be general to the specific in the vertical.
Example
Cell Header | Cell Header | Cell Header | |
---|---|---|---|
Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="2">Cell Header</th>
<th colspan="2">Cell Header</th>
<th rowspan="2">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | ||
---|---|---|---|
Cell Header | Cell Header | ||
Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="3">Cell Header</th>
<th colspan="3">Cell Header</th>
</tr>
<tr>
<th rowspan="2">Cell Header</th>
<th colspan="2">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | ||
---|---|---|---|
Cell Header | Cell Header | ||
Cell Header | Cell Header |
Source Code
<table>
<tr>
<th rowspan="3">Cell Header</th>
<th colspan="3">Cell Header</th>
</tr>
<tr>
<th colspan="2">Cell Header</th>
<th rowspan="2">Cell Header</th>
</tr>
<tr>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | ||
---|---|---|---|
Cell Header | Cell Header | ||
Data Row | Data Cell | Data Cell | Data Cell |
Source Code
<table>
<tr>
<th rowspan="2">Cell Header</th>
<th colspan="3">Cell Header</th>
</tr>
<tr>
<th colspan="2">Cell Header</th>
<th>Cell Header</th>
</tr>
</table>
Bad Example
Cell Header | Cell Header | Cell Header |
---|---|---|
Cell Header |
Source Code
<table>
<tr>
<th rowspan="2">Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<th colspan="2">Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | ||
---|---|---|---|
Cell Header | Cell Header | Cell Header | |
Cell Header |
Source Code
<table>
<tr>
<th rowspan="3">Cell Header</th>
<th colspan="3">Cell Header</th>
</tr>
<tr>
<th rowspan="2">Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<th colspan="2">Cell Header</th>
</tr>
</table>
Cell Header | Cell Header | Cell Header | Cell Header |
---|---|---|---|
Cell Header | |||
Cell Header |
Source Code
<table>
<tr>
<th rowspan="3">Cell Header</th>
<th rowspan="2">Cell Header</th>
<th>Cell Header</th>
<th>Cell Header</th>
</tr>
<tr>
<th colspan="2">Cell Header</th>
</tr>
<tr>
<th colspan="3">Cell Header</th>
</tr>
</table>
Paralel column/row header are not allowed except for group header
When a paralel column/row header are found, that cause an hiarchical issue. In the case of a column, may be that information can be moved at the top of it's parent cells, or merged if they already have one, or that information need to be more structured to fit in the current table context. This can be resolved often by moving the content into an another table. See the section about "Having a second column heading set"
Delimiting the column heading with a row group heading
After the column heading, a row group header can be specified. That row header will be spanned in the full table width.
Cell overflow between data group
A cell can not overflow between row group. But they can overflow between column group. (HTML5 specification). See "Have a proportional table" for more details.
Data row
A data row is a table row that it's last cell are a data cell ("td" element). A data row can have a data cell between of two different level of row header cell
Here a data row
Data | Data | Data | Data |
Header | Data | Data | Data |
---|
Data | Header | Data | Data |
---|
Data | Data | Header | Data |
---|
This are not a valid data row, because it's last cell are a cell header. The only row can finish with a cell heading is the row used in the rowgroup header (thead) and/or a row group header inside the data table (tbody)
Data | Data | Data | Header |
---|
This is true even if data cell are between headers, a data need to finish with a "td"
Header | Data | Data | Header |
---|
Group
A group are a set of row or column. When the group are a set of row, this is an row group. And when the group are a set of column, this is a column group. They exist three type of group
- Header group
- Data group
- Summary group
Header group
Header row group
The header row group is delimited by a "thead" element. It's composed only of cell heading (th), optionally they can only contain one layout cell located at it's first column group. The header row group are always at the top of the table. The end can be marked by a rowgroup header spanned by the full table width or just the row before a data cell are found.
Header column group
The header column group are be delimited by a "colgroup" element. It's composed only of cell heading (th). Optionally, the first header column group if it is the first colgroup also can contain one layout cell in his first row. Differently of header row group, a table can have more than one header column group.
<colgroup id="a" /><colgroup id="b" /><colgroup id="c" /><colgroup id="d" span="2" /><colgroup id="e" />
Cell Header [1] | Cell Header [2] | Cell Header [3] | Cell Header [4] | Cell Header [5] | Cell Header [6] |
---|---|---|---|---|---|
Cell Header [7] | Data cell [8] | Cell Header [9] | Data cell [10] | Data cell [11] | Data cell [12] |
Cell Header [13] | Data cell [14] | Data cell [15] | Data cell [16] | ||
Cell Header [17] | Data cell [18] | Data cell [19] | Data cell [20] |
If you take a look closer of the colgroup defined in the previous table, you will be noticed that the last column are a summary column group. The column group type are defined are the following:
- colgroup id="a" : header column group
- colgroup id="b" : data column group
- colgroup id="c" : header column group
- colgroup id="d" : data column group
- colgroup id="e" : summary column group
Cell associated to the...
- header column group "a": 7
- data column group "b": 8
- header column group "c": 9, 13, 17
- data column group "d": 10, 11, 14, 15, 18, 19
- summary column group "e": 12, 16, 20
The summary column group are only applying to the preceding data column group (id="d")
If you would like to have more than one summary column group, would would need to define two row or more in your header row group.
table><colgroup id="a" /><colgroup id="b" /><colgroup id="c" /><colgroup id="d" span="2" /><colgroup id="e" /><colgroup id="f" span="2" /><colgroup id="g" />
Cell Header [1] | Cell Header [2] | Cell Header [3] | Cell Header [4] | Cell Header [5] | ||||
---|---|---|---|---|---|---|---|---|
Cell Header [6] | Cell Header [7] | Cell Header [8] | Cell Header [9] | Cell Header [10] | Cell Header [11] | |||
Cell Header [12] | Data cell [13] | Cell Header [14] | Data cell [15] | Data cell [16] | Data cell [17] | Data cell [18] | Data cell [19] | Data cell [20] |
Cell Header [21] | Data cell [22] | Data cell [23] | Data cell [24] | Data cell [25] | Data cell [26] | Data cell [27] | ||
Cell Header [29] | Data cell [30] | Data cell [31] | Data cell [32] | Data cell [33] | Data cell [34] | Data cell [35] |
- colgroup id="a" : header column group
- colgroup id="b" : data column group
- colgroup id="c" : header column group
- colgroup id="d" : data column group
- colgroup id="e" : summary column group
- colgroup id="f" : data column group
- colgroup id="g" : summary column group
Cell associated to the...
- header column group "a": 12
- data column group "b": 13
- header column group "c": 14, 21, 29
- data column group "d": 15, 16, 22, 23, 30, 31 (Identified by the cell header group 4)
- summary column group "e": 17, 24, 32 (Identified by the cell header group 4)
- data column group "f": 18, 19, 25, 26, 33, 34 (Identified by the cell header group 5)
- summary column group "g": 20, 27, 35 (Identified by the cell header group 5)
Column group are identified by...
- header column group "a": Cell Header 1
- data column group "b": Cell Header 2
- header column group "c": Cell Header 3
- data column group "d": Cell Header 4
- summary column group "e": Cell Header 4
- data column group "f": Cell Header 5
- summary column group "g": Cell Header 5
Data group
A data group is a set of one or more column or row consecutive that contains majority of data cell.
Data column group
Data row group
There exist 4 kind of data row group. The first are the data set associated directly to the table level. The second are a summary group of the table level and they need to have a rowgroup header specified. The third are the sub-group data row group summary. And the fourth data row group are the table data row group summary. Even the table parser allow you to have an infinite sub row group by desiging you row in a hiearchical way, it's imposible for the parser, when we are into an hiearchical sub row group, to know the difference between if a data row belong to the summary, or if the data row belong to the data set. There are only two way that relation can be showed. By using nested table or by using two differents data row structure.
Summary group
Their use are defined with the header column group and the data row group. Important to know about summary group is that row group can be used to replace their associated data group for a quick data interpretation. Also to be able to have a valid summary group, it's required to have at least to data cell.
Data cell
A data cell are the result of the intersection of two data groups. That can not be an intersection of two header group and can or can not be an intersection of two summary group.
Data row partern
In general there are only one data partern for each data row. But when there are a second data parten, this are often interpretated as a summary row group.
Simplify your data cell
I recommand to design your cell data in the most basic form. Like if possible, having only the value or only the combinaison value and measure. If you use measure in your cell, be consistant across all the cell in the same column.
You have a data row with the following heading like this:
Service | Commitment | Expectation |
---|---|---|
Issue filing date | within 4 weeks upon receipt of application that meets filing requirements including fees | 90% |
Souce Code
<table>
<tr>
<th>Service</th>
<th>Commitment</th>
<th>Expectation</th>
</tr>
<tr>
<th>Issue filing date</th>
<!-- This is the problematic cell -->
<td>within 4 weeks upon receipt of application that meets filing requirements including fees</td>
<td>90%</td>
</tr>
</table>
Here a fix you can made (with details/summary in the cell header)
Service | Commitment | Expectation |
---|---|---|
Issue filing datewithin [time] upon receipt of application that meets filing requirements including fees |
4 weeks | 90% |
Souce Code
<table>
<tr>
<th>Service</th>
<th>Commitment</th>
<th>Expectation</th>
</tr>
<tr>
<th>
<details>
<summary>Issue filing date</summary>
<p>within [time] upon receipt of application that meets filing requirements including fees</p>
</details>
</th>
<!-- See, the content was simplified -->
<td>4 weeks</td>
<td>90%</td>
</tr>
</table>
Here an another way to do it (with footnote)
Service | Commitment | Expectation |
---|---|---|
Issue filing date | 4 weeks1 | 90% |
1 within [time] upon receipt of application that meets filing requirements including fees
Souce Code
<table>
<tr>
<th>Service</th>
<th>Commitment</th>
<th>Expectation</th>
</tr>
<tr>
<th>
<details>
<summary>Issue filing date</summary>
<p></p>
</details>
</th>
<!-- See, the content was simplified -->
<td>4 weeks<sup><a href="#">1</a></sup></td>
<td>90%</td>
</tr>
</table>
<p><sup>1</sup> within [time] upon receipt of application that meets filing requirements including fees</p>
How to add a cell description in a table
Use the same method of the "Simplify your cell data"
Have a proportional table
It's simple but fondamental for the parsing. For each row and col, the cell length (span or/and number of "th"/"th") must be equal. When the rowgroup are used, it's not allowed for a cell to be spanned outside his rowgroup, but a cell can be spanned outside of it's colgroup in specific case. HTML5 requirement - 4.9.12 Processing model ( paragraph nine and ten)
How to use "colgroup" and "col" element
The colgroup is realy similar of a rowgroup but in the column perpective. If present, the "col" element definition will be used to identify the lower row header in the rowgroup heading ("thead" if defined). A colgroup can represent a heading set defined in a data row, represent only a set of data cell. A colgroup can also contain heading cell and data cell.
Spanned Cells
In general when a cells are span in multiple row and column, they need to have a corresponding group to get associated to. The HTML5 specification said that a cell not be spanned in two row group, but they can be spanned in serveral colgroup.
Why a cell can be spanned in more than one column group ? It's simple, as this usability guide define a data table to be equal to a rowgroup make easy to explain why. If we took the caption of an table for a row group cell header, this cell is spanned in serveral columns group, equivalent to the table width. When a cell are span in two or more column group, that cell needs to be equivalent to the table width, if not that would be a mistake. Those special cell is used here to represent sub row group. And after a sub row group like that, the following data cell if is colspan attribute are equivalent to his heading are used to indicate the possibility of a nested table.
Can I have a cell spanned without having an group header associated ? Yes it's possible. We can take for example a schedule like Outlook or we can think about a online TV guide. With those exemple, the relation between a data cell and his header are different. The headers will act more as a property of the data instead of identifying them. The question that would need to be answered is: Is those kind of table are valid data table ? If yes, is there a method to recognize them ? That will be leaved for the future.
Nested tables
A complex data tables can have nested tables. It's recommended to avoid this, but in a case of a tree grid this will be useful to do. The sub-tables can not be integrated everywhere, they need to be under a row group header inside the next data cell.
Filed | Granted | |||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Canada | ||||||||||||||||||||||||||||||||
Alberta | 746 | 400 | ||||||||||||||||||||||||||||||
British Columbia | 409 | 144 | ||||||||||||||||||||||||||||||
Manitoba | 106 | 42 | ||||||||||||||||||||||||||||||
New Brunswick | 26 | 13 | ||||||||||||||||||||||||||||||
Newfoundland and Labrador | 16 | 6 | ||||||||||||||||||||||||||||||
Northwest territories | 1 | 0 | ||||||||||||||||||||||||||||||
Nova Scotia | 53 | 21 | ||||||||||||||||||||||||||||||
Ontario | 2122 | 884 | ||||||||||||||||||||||||||||||
Prince Edward Island | 7 | 0 | ||||||||||||||||||||||||||||||
Quebec | 871 | 408 | ||||||||||||||||||||||||||||||
Saskatchewan | 120 | 62 | ||||||||||||||||||||||||||||||
Sub Total | 4477 | 1980 | ||||||||||||||||||||||||||||||
Foreign Countries (The following are a nested table) |
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
Total | 35318 | 19779 |
Documentation/Idea to work on
- How to do Nested tables in a data cell spanned in the full table width with a preceding cell heading spanned in the full table width....[tree grid] ;-)
TODO: set a usability limit about the number of row inside the header row group and a limit regarding the number of consecutive rowgroup header we can have in a table. I think regarding the number of row group cell header spanned into the full with, a maximum of 2 are resonable starting from the most generic to the most specific.
- Date modified: