Responsive Data Tables: A Comprehensive List of Solutions

Originally published at: http://www.sitepoint.com/responsive-data-tables-comprehensive-list-solutions/

Tables are an important part of HTML. Although they were often used in the past for layout, today they’re mainly used for marking up data. Since the adoption of responsive web design, various approaches have been developed for establishing tables that can scale well in different viewport sizes.

In this article, I’ll go over and analyze many of these approaches. Keep in mind that I’ll be focused mostly on the JavaScript-based ones, as I think they offer more options and features compared to the pure CSS solutions. To make things easier and clearer, this article is full of helpful images and demos.

The Basic Markup for Our Table

Before diving into the core methods, let’s have a look at the example table that will be used throughout this article to demonstrate the different methods for achieving responsive tables:

<table summary="Example table">
    <caption>Example Table Caption</caption>
    <thead>
        <tr>
            <th>Country</th>
            <th>Languages</th>
            <th>Population</th>
            <th>Median Age</th>
            <th>Area (Km²)</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Argentina</td>
            <!-- more cells here... -->
        </tr>
        <!-- more rows here... -->
    </tbody>
    <tfoot>
        <tr>
            <td colspan="5">
                <!-- content here... -->
            </td>
        </tr>
    </tfoot>
</table>

Note that with the exception of the Foundation example, the styling of this table will be based on Bootstrap’s table styles.

Let’s now get familiar with different techniques for building responsive tables.

Bootstrap’s Responsive Tables

To create a responsive table with Bootstrap, you have to wrap the table inside a div element with a class of table-responsive. By default, Bootstrap applies the overflow-x: auto property to this wrapper element. When the browser window is less than 768px, the overflow-y: hidden property is applied. Therefore, on small devices you can see the contents of your tables by scrolling horizontally.

The following screenshot demonstrates what’s described above:

Continue reading this article on SitePoint

I was hoping to see a comparison with the new ng responsive tables that are suppose to be very fast.

Well, I made this responsive tables plugin called Tabella.js and I can’t tolerate it was ignored in this article :slight_smile: take a look if you want

Your tfoot is in the wrong place. The tfoot must come before the first tbody as when printing out on paper the tfoot needs to print on every page and depending on where on the page the table starts you don’t know how many rows of tbody will appear before the first print of the first tfoot.

As far as I know, with HTML5 you can place your tfoot either before tbody or after it. Previous versions, require tfoot before tbody. See the link.

Yes I noticed that the other day.It seemed a strange thing to change unless they assumed that most people were doing it wrong anyway.

How is the tbody supposed to print in the right place if it comes after the tbody. Each time there is a page break inside the tbody there is no tfoot data to print if the tfoot is at the bottom.

Presumably a tfoot at the bottom is simply treated as another tbody since it can’t print at the bottom of every page the way it could if it were correctly positioned at the top.

For the next standard let’s declare pi equal to 3. That will work just as well as allowing the tbody to go at the bottom where it will not be available until long after it is needed.

Firefox seems to handle tfoot after the tbody the same as if it were after thead. That is it prints the footer and header on each printed page either way. (I’m sure it must take a lot more processing to do that.)

It seems a silly thing to change to me.

2 Likes

Yes - it means that it has to do a double pass through the HTML so as to get the tfoot before it starts processing the tbody.

Even if it works it would slow the loading of the page while it gets the tfoot from where ever it is lower down in the HTML.

If browsers look for the tfoot further down the source then presumably always including a tfoot (even if empty) just after the thead would speed up the loading of the page as then it doesn’t need to read the table twice.

1 Like

The summary attribute on the table element is obsolete (http://www.w3.org/TR/html-markup/table.html).

Yeah, that’s true, yet many people still using it (see for example Foundation’s docs). I could have omitted it as I have already defined a caption.

Thank you, a useful list of options.

I tried using TableSaw yesterday (before seeing this article) but it wasn’t all that easy, and it made nonsense of my table because it dropped all my column headings (days of the week). If it were possible to avoid that I failed to work out how.

My table is a calendar, with days of the week horizontally and months vertically. Allowing for different start days, it comes out at about 38 columns wide (most of them narrow, fortunately). All the data comes from a MySQL DB via PHP, so my solution was simply to make an entirely new set of tables (one per month), each only one week wide. It only added about 80 lines of code to the existing PHP. Finally a media query to hide/display the appropriate table(s).

I’m sure there are times when a plug-in will be a better solution, but let’s not forget there are others. See it at: http://seaviewmull.co.uk/availability/2015

But the spec is wrong about that – its obsolete status is based on a misunderstanding of its purpose.

The summary attribute should describe the structure of the table, while the caption describes its content. A data table should have both.

So in this example, the summary would be something like “This table has a row for each country, and a column for each piece of data about that country”.

You should also have “scope” attributes on the TH cells :smile:

And I would strongly advise against that Foundation solution, because it has poor accessibility – splitting the table into two tables where the headers in one are undisplayed and the data in the other is undisplayed, means that a screenreader can’t get coherent data from either of the tables. The same applies to any solution that splits and hides the table content – the integrity of the data structure must be maintained.

3 Likes

Here is one i picked up on google without any framework

The HTML:

<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>

The 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; 
}

The Media Queries:

/* 
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
@media 
only 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: "Porn Name"; }
    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"; }
}

REFERENCE: https://css-tricks.com/responsive-data-tables/

I agree that Foundation’s responsive table solution is a usability fail. First, on a recent version of an iphone, you don’t see any visual cue that you can independently scroll on the first long cell vs the rest of the cells.

Second, the markup removes the table caption, which serves a purpose for screen readers and accessibility.

The Google solution is intriguing, and I found something similar here: http://codepen.io/colintoh/pen/kbrzL

Yeah that’s basically the approach I take too, except that I prefer to code the table headers into data attributes, then you can define them in a single CSS rule without having to specify content in the stylesheet, i.e:

<td data-header="First Name">James</td>

Then:

td::before { content:attr(data-header); }

Yes I use the similar method mentioned by brothercake but you should note that the table-cells in ie9 and under do not collapse in to blocks and break the layout.

The solution is pretty easy and you also need to set the td,tr,th, to float:left and width:100% and then IE9 and ie8 can play also :smile:

e.g.

  table, thead, tbody, th, td, tr { 
        display: block; 
	    float:left;
       width:100%;
      clear:both;
    }

The display:block then becomes redundant but I leave it in anyway in case the float gets removed by accident.

Yeah right, and if you play with the floats and widths you can usually get away without needing absolute positioning (i.e. float the pseudo-element to the left of the TD content, rather than absolutely positioning it).

Another approach is to use display:table on each TD and then display:table-cell on the pseudo-element (or, wrap the TD content in a SPAN, and then use display:table-cell on both the pseudo-element and the SPAN, to give you more control). Though that only really works in IE9 or later.

Could probably do it with flexbox too, but I’ve never tried that :smile:

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.