How it works

Mark up each td with a data attribute with the corresponding <th>. So if <td>USA</td> was our item and it appeared under the heading <th>Country</th> I might add it like this -> <td data-heading=Country>USA</td>.

Then what I do is usually display it like a beautiful normal table above 700 or 800 px, and for thin tablets, phone landscape, and phone portrait I'll do a reset of all table-related elements making them block. Once the table is reset for mobile, I now think about each <tr> as a design unit. I often will use the first <td> as a heading and then for other td elements in the <tr> I'll use the data-heading as a before element, and make a 2-column chart with each td as a row of two cells of data.

HTML

Here's some sample <table> markup that will work with this:

  <table>
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
      <th>Header 3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Cell 1</td>
      <td>Cell 2</td>
      <td>Cell 3</td>
    </tr>
    <tr>
      <td>Cell 6</td>
      <td>Cell 7</td>
      <td>Cell 8</td>
    </tr>
    <tr>
      <td>Cell 11</td>
      <td>Cell 12</td>
      <td>Cell 13</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th>Footer 1</th>
      <th>Footer 2</th>
      <th>Footer 3</th>
    </tr>
  </tfoot>
</table>

JavaScript

If you don't want to mark up the <td data-heading=""> values by hand, here's a JavaScript plugin I use to scan pages for a table and mark it up automatically:

  var tables = document.getElementsByTagName('table');
for (i=0;i<tables.length;i++){
  var headers = tables[i].getElementsByTagName('th'),
      rows = tables[i].getElementsByTagName('tr'),
      header = [];
  if (tables[i].getAttribute('data-table') == undefined) {
    tables[i].setAttribute('data-table',i)
  }
  if (tables[i].getAttribute('data-table-theme') == undefined) {
    tables[i].setAttribute('data-table-theme','default')
  }
  for (h=0;h<headers.length;h++){
    header.push(headers[h].innerHTML);
  }
  for (r=0;r<rows.length;r++){
    var cells = rows[r].getElementsByTagName('td');
    for (c=0;c<cells.length;c++){
      if (cells[c].getAttribute('data-header') == undefined && header[c] !== undefined) {
        cells[c].setAttribute('data-header',header[c]);
      }
    }
  }
}

Styles

Here's the CSS, including a mobile reset for table elements, turning them to block, and a reset back to normal size

CSS

  @media (max-width: 400px) {
  table,
  table caption,
  table thead,
  table tbody,
  table tfoot,
  table tr,
  table th,
  table td { display: block; width: 100%; }
}
@media (min-width: 400px) {
  table { display: table; width: auto; }
  table caption { display: table-caption; width: auto; }
  table thead { display: table-header-group; width: auto; }
  table tbody { display: table-row-group; width: auto; }
  table tfoot { display: table-footer-group; width: auto; }
  table tr { display: table-row; width: auto; }
  table th,
  table td { display: table-cell; width: auto; }
}

Element Queries

Here's the same code using element queries, powered by the EQCSS plugin:

  @element 'table' and (max-width: 400px) {
  $this,
  $this caption,
  $this thead,
  $this tbody,
  $this tfoot,
  $this tr,
  $this th,
  $this td { display: block; width: 100%; }
}
@element 'table' and (min-width: 400px) {
  $this { display: table; width: auto; }
  $this caption { display: table-caption; width: auto; }
  $this thead { display: table-header-group; width: auto; }
  $this tbody { display: table-row-group; width: auto; }
  $this tfoot { display: table-footer-group; width: auto; }
  $this tr { display: table-row; width: auto; }
  $this th,
  $this td { display: table-cell; width: auto; }
}

The advantage of element queries being that these breakpoints would be tied to the width of the <table> element itself, not the width of the browser. This one set of breakpoints could handle the responsive support for every table on a website, regardless of which layouts it appears in. The same styles (thanks to style scoping and the $this meta-selector) can also power multiple <table> elements at different widths on the same page at the same time without changing the styles of all of them.

Example Responsive Tables


1,048 0 5