Responsive Tables

A few weeks back, I spent time researching how best to build responsive tables.

Our requirements were pretty simple. We wanted the ability to load data from Google Drive, the ability to embed the tables using an iframe and a dead simple way of handling (re)publication.

Of course, the other essential requirement for responsive tables is that they work well on a variety of devices. In my opinion, the best solutions to this problem transform your table into an easily scrollable list of data on smaller devices.

To handle the transformation of the table on smaller screens, I started by using jQuery DataTables and writing my own code, but came across Tablesaw.js, which already solved the problem.

For the other requirements, I settled on Tabletop.js to handle loading the data, Pym.js for embedding via iframe and a tiny render script, written in Python, to make generating a ready-to-deploy responsive table quick and easy.

How it works

Once you’ve set up a spreadsheet in Google Drive and grabbed the spreadsheet’s public key (described in the Tabletop.js documentation), clone the responsive-tables repository.

First, you’ll want to install requirements, optionally creating a virtualenv:

$ mkvirtualenv tables
$ pip install -r requirements.txt

If you’re not familiar with Python, pip and virtualenv, read more about them here.


Next, you’ll create a config file for your table. You can get started by copying the example:

$ cp config-example.json config.json

Edit config.json, filling in each of the blanks with your information.

The ua_code field is your Google Analytics UA code in the format “UA-XXXXXXXX-X”. If you leave it blank or remove it, Google Analytics will be disabled.

The columns field determines which parts of the data from Google Drive should be included in the table. The data structure defining the columns is an array of arrays. Each array within the array represents a column and contains two items.

The first is the column identifier. This is the lowercase column title stripped of punctuation. For example, if your column title is “Must be 501(c)(3)?” your column identifier would be “mustbe501c3.”

The second is how you’d like the column title to appear in your rendered table. You can stick with the title you used in Google Drive or change it entirely. For example, you could use “Must be 501(c)(3)?” or instead choose “Need 501(c)(3).”

The config.json file for the example looks like:

  "ua_code": "UA-20502211-1",
  "title": "Discounts for nonprofits",
  "key": "10yccwbMYeIHdcRQazaNOaHSkpoSa1SUJEtWBfWPsgx0",
  "columns": [
    ["service", "Service"],
    ["whatisit", "What is it?"],
    ["whatsthediscount", "What's the discount?"],
    ["mustbe501c3", "Must be 501(c)(3)?"],
    ["moreinfo", "More info"]

Rendering your table

Once you’ve created a config file, you can render the table by running:

$ ./

This will create a build directory adjacent to and populate it with all of the files required to deploy the table. Note that if a build directory exists, anything within it will be deleted when calling

Once that’s finished, upload the contents of the build directory to your host of choice.

Other notes

The table’s breakpoint is set to 60em (or 960px). There is currently no simple way to change this value, which is why the README states this rig is best suited for tables with 5-7 columns. We may work out a simple way to adjust this in the future.

Also note, the file assets/responsiveTable.js contains some code that identifies long urls in your table’s data, converts them to actual anchor tags and uses css to truncate their text to avoid ruining the table’s lovely responsiveness. You can adjust the width at which the text is truncated in style.css:

#data a.ellipsis-link {
  display: inline-block;
  max-width: 180px; /* adjust the width of truncated urls */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;

You can see an example of a table rendered with our rig here:

And an example of that same table embedded via iframe:

View and fork the code here: