✎ Technique: Orientation

Content does not restrict its view and operation to a single display orientation, such as portrait or landscape, unless a specific display orientation is essential (i.e., bank check). 

A phone, tablet, and desktop display, allow showing illustrations representing the same content.

(Source: Affinity Bridge on responsive design

Examples

✗ Bad example: let the user determine how best to access content 

Non-responsive design forces users to make compromises, use extra time and exert additional effort to access information. And, in cases where users have mobility or other physical limitations, the information may be completely inaccessible. 

Left: a few columns of a table on a phone in portrait orientation. Right: the same table on the same phone, the whole table fits but the content is tiny.

(Source: CSS-TRICKS article on responsive tables)

✓ Good example: adopt a responsive front-end framework

Phone displaying tabular data reformatted into a list-like design; each row has what was a column header next to one cell's data. Background colors separate the data from each original table row.

(Source: CSS-TRICKS article on responsive tables)

Use "responsive design" principles (CSS @media queries) to detect if the screen is smaller than the maximum width of the table. If it is, the table gets reformatted, by

  1. Hiding the table headers (although still accessible by screen readers)
  2. Creating a new column with table headers placed in table rows.
  3. Displaying the content of each row within a single column

HTML table:

<table>
 <thead>
  <tr>
   <th>First Name</th>
   <th>Last Name</th>
   <th>Job Title</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>James</td>
   <td>Matman</td>
  <td>Chief Sandwich Eater</td>
  </tr>
  <tr>
   <td>The</td>
   <td>Tick</td>
   <td>Crimefighter Sorta</td>
  </tr>
 </tbody>
</table>

CSS:

/* Generic Styling, for Desktops/Laptops */
table {
   width: 100%;
   border-collapse: collapse;
 }
/* Zebra striping */
tr:nth-of-type(odd) {
   background: #eee;
 }
th {
   background: #333;
   color: white;
   font-weight: bold;
 }
td, th {
   padding: 6px;
   border: 1px solid #ccc;
   text-align: left;
 }

CSS for table-related elements

Change every table-related element to be block-level then for each "cell", use CSS generated content (:before) to apply the "column header" to label the content originally shown in each row.

/* Max width will take effect for any screen smaller than 760px and also iPads specifically. */
@mediaonly screen and (max-width: 760px),(min-device-width: 768px) and (max-device-width: 1024px) {
/* Force table to not be like tables anymore */
  table, thead, tbody, th, td, tr {
    display: block;
  }
/* Hide table headers (but not display: none;, for accessibility) */
  thead tr {
    position: absolute;top: -9999px;
    left: -9999px;
  }
  tr {
    border: 1px solid #ccc;
 }
  td {
    /* Behave like a "row" */
    border: none;
    border-bottom: 1px solid #eee;
    position: relative; 
    padding-left: 50%;
  }
  td:before {
    /* Now like a table header */
    position: absolute;
    /* Top/left values mimic padding */
    top: 6px;
    left: 6px;
    width: 45%;
    padding-right: 10px;
    white-space: nowrap;
  }
/* Label the data */
  td:nth-of-type(1):before { content: "First Name"; }
  td:nth-of-type(2):before { content: "Last Name"; }
  td:nth-of-type(3):before { content: "Job Title"; }
  td:nth-of-type(4):before { content: "Favorite Color"; }
  td:nth-of-type(5):before { content: "Wars of Trek?"; }
  td:nth-of-type(6):before { content: "Secret Alias"; }
  td:nth-of-type(7):before { content: "Date of Birth"; }
  td:nth-of-type(8):before { content: "Dream Vacation City"; }
  td:nth-of-type(9):before { content: "GPA"; }
  td:nth-of-type(10):before { content: "Arbitrary Data"; }
}