118

Hi all it's been a while since I've asked something, this is something that has been bothering me for a while, the question itself is in the title:

What's your preferred way of writing HTML tables that have vertical headers?

By vertical header I mean that the table has the header (<th>) tag on the left side (generally)

Header 1 data data data
Header 2 data data data
Header 3 data data data

They look like this, so far I've come up with two options

First Option

<table id="vertical-1">
    <caption>First Way</caption>
    <tr>
        <th>Header 1</th>
        <td>data</td><td>data</td><td>data</td>
    </tr>
    <tr>
        <th>Header 2</th>
        <td>data</td><td>data</td><td>data</td>
    </tr>
    <tr>
        <th>Header 2</th>
        <td>data</td><td>data</td><td>data</td>
    </tr>
</table>

The main advantage of this way is that you have the headers right (actually left) next to the data it represents, what I don't like however is that the <thead>, <tbody> and <tfoot> tags are missing, and there's no way to include them without breaking the nicelly placed together elements, which lead me to the second option.

Second Option

<style type="text/css">
    #vertical-2 thead,#vertical-2 tbody{
        display:inline-block;
    }
</style>
<table id="vertical-2">
    <caption>Second Way</caption>
    <thead>
        <tr>
            <th colspan="3">Header 1</th>
        </tr>
        <tr>
            <th colspan="3">Header 2</th>
        </tr>
        <tr>
            <th colspan="3">Header 3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>row 1</td>
            <td>row 1</td>
            <td>row 1</td>
        </tr>
        <tr>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
        <tr>
            <td>data</td>
            <td>data</td>
            <td>data</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td colspan="4">Footer</td>
        </tr>
    </tfoot>
</table>

The main advantage here is that you have a fully descriptive html table, the drawbacks are that proper representation needs a bit of CSS for the tbody and thead tags and that the relation between the headers and data isn't very clear as I had my doubts when creating the markup.


So, both ways render the table how it should, here a pitcure:

render
With the headers on the left or right side if you would prefer it, so, any suggestions, alternatives, browser issues?

Community
  • 1
  • 1
Tristian
  • 3,406
  • 6
  • 29
  • 47

4 Answers4

57

First, your second option isn't quite valid HTML in the sense that all of the rows (TR) in a table should contain an equal number of columns (TD). Your header has 1 while the body has 3. You should use the colspan attribute to fix that.

Reference: "The THEAD, TFOOT, and TBODY sections must contain the same number of columns." - Last paragraph of section 11.2.3.

With that being said, the first option is the better approach in my opinion because it's readable regardless of whether or not I have CSS enabled. Some browsers (or search engine crawlers) don't do CSS and as such, it'll make your data make no sense as the header will then represent columns instead of rows.

Francois Deschenes
  • 24,816
  • 4
  • 64
  • 61
  • Is it really necessary for him to fix that first problem you mentioned? Since if you only add one cell, it automatically takes the first space and the rest gets ignored? – Pangolin Jun 16 '11 at 06:55
  • hi thanks for highlighting the invalid markup, I'll correct it. – Tristian Jun 16 '11 at 07:02
  • @Nideo - I've added a reference from the HTML4 documentation in my post that clearly states that THEAD, TFOOT and TBODY must contain the same number of columns. – Francois Deschenes Jun 16 '11 at 07:02
  • @Triztian - One more thing. The TFOOT should be directly below the THEAD (and before the TBODYs). Again, this is covered in section 11.2.3 of the HTML specification. – Francois Deschenes Jun 16 '11 at 07:07
  • SO, does adding the `colspan` attribute to the headers we validate the markup? – Tristian Jun 16 '11 at 07:10
  • Is the `scope` attribute for `th` tags still valid? I always assume you use the first approach and then you do `th scope="row"` or is the `scope` definition supposed to be used in `thead`? – prodigitalson Jun 16 '11 at 07:14
  • @Triztian - Adding the `colspan` attribute to the columns in the THEAD and TFOOT and moving the TFOOT above the TBODY will make it proper HTML... but it won't make it right. Again, think about visually impaired people, web crawlers, etc. that don't use CSS. Your table won't make any sense. You should be able to look at the table without any CSS and still be able to understand it. – Francois Deschenes Jun 16 '11 at 07:14
  • 1
    @prodigitalson - The `scope` attribute wouldn't really make much of a difference in this case. If you read what it's for, you'll understand. It basically means that the that columns is the header for either the row or column it contains. The problem is it's use doesn't make sense unless if was to replace the `` with a ``. – Francois Deschenes Jun 16 '11 at 07:17
6

The First Option... I think it is the better and simple approach..

Philemon philip Kunjumon
  • 1,417
  • 1
  • 15
  • 34
5

Honestly, option 1. I would suggest you to look at this example from W3.org(link below). I think this method is the best, because this way your headings will also be interpreted right on screen readers.

https://www.w3.org/WAI/tutorials/tables/one-header/#table-with-header-cells-in-the-first-column-only

Dmitri Chebotarev
  • 2,429
  • 1
  • 11
  • 7
-5

div.vertical {
  margin-left: -85px;
  position: absolute;
  width: 215px;
  transform: rotate(-90deg);
  -webkit-transform: rotate(-90deg);
  /* Safari/Chrome */
  -moz-transform: rotate(-90deg);
  /* Firefox */
  -o-transform: rotate(-90deg);
  /* Opera */
  -ms-transform: rotate(-90deg);
  /* IE 9 */
}

th.vertical {
  height: 220px;
  line-height: 14px;
  padding-bottom: 20px;
  text-align: left;
}
<table>
  <thead>
    <tr>
      <th class="vertical">
        <div class="vertical">Really long and complex title 1</div>
      </th>
      <th class="vertical">
        <div class="vertical">Really long and complex title 2</div>
      </th>
      <th class="vertical">
        <div class="vertical">Really long and complex title 3</div>
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Example</td>
      <td>a, b, c</td>
      <td>1, 2, 3</td>
    </tr>
  </tbody>
</table>
Undo
  • 25,519
  • 37
  • 106
  • 129
  • 5
    Please add an explanation as to how your answer addresses the issue identified in the question. – blurfus Jul 14 '17 at 17:21