Responsive HTML Tables

If you have ever built a webpage that includes a wide HTML table, you have likely ran into the problem of how to make it display in a usable way on various common view port sizes. I have researched ideas to solve this but I haven’t been 100% happy with the solutions I have found. Usually there is some facet of a good webpage that is not being satisfied such as semantics, accessibility, or usability. I also don’t like to install additional JavaScript libraries unless absolutely necessary.

I have come up with my own solution that to the best of my knowledge I haven’t seen elsewhere. The following solution discussed is specific to WordPress but the concept can easily be adapted to other platforms.

Summary/Details of Solution:

  • On the template itself in PHP, it outputs 2 copies of the table. One for large view and another for small. The small view is actually a series of individual tables.
  • The large and small table displays are visible based on the visibility classes of whatever front end framework you happen to be using. In my case I am using Foundation 6, but this can easily be adapted for use with Bootstrap. Custom visibility classes can also be used too.
  • I feel the small view of the table display presents a more semantically correct HTML table structure compared to some of the other solutions I found online
  • If images are being displayed in table cells there is no concern for images being downloaded twice (once for the large table view and again for the small view). Once the browser downloads the image the first time, it will be cached in the browser and won’t be downloaded again (as long as the file paths are the same)
  • No need for additional front end libraries to handle responsive tables
  • This approach does have time complexity (on server side PHP code) of O(2n). On the server side, ‘the loop’ for the table data is being executed twice (once for the large table output and again for the small). It is not exactly double the execution time though. Once the WP_Query object fetches the data results, the data will be cached for the second iteration of the loop.
  • This approach does result in additional HTML being sent to the web browser. This is pure HTML text and will have a negligible effect on page load time in most cases
  • This approach can also be adapted for static tables.

Here is the template code. This shows a simple example and can be adapted for your specific needs:

<h3>Responsive Table</h3>
<div class="show-for-small-only" >
  <!-- 'show-for-small-only' is a utility class for the foundation 6 framework which only displays on small view ports -->

  <?php
    
    $args = array(
      'post_type'      => array('post'),
      'posts_per_page' => -1,
    );                  
    
    $post_query = new WP_Query( $args );

    if ( $post_query->have_posts() ) {
      while ( $post_query->have_posts() ) {
        $post_query->the_post();
        ?>
          <table>
            <caption><?php the_title(); ?></caption>
            <tr>
              <th>Post Date</th>
              <td><?php the_Date(); ?></td>
            </tr>
            <tr>
              <th>Post Status</th>
              <td><?php echo get_post_status(); ?></td>
            </tr> 
            <tr>
              <th>Post Type</th>
              <td>
                <?php echo get_post_type(); ?>
              </td>
            </tr>
            <tr>
              <th>Featured Image</th>
              <td><?php the_post_thumbnail(); ?></td>
            </tr>                           
          </table>
        <?php
      }
    } else {
      ?>
        <p>No posts to display.</p>
      <?php
    }

    $post_query->rewind_posts();

  ?>
</div>
<div class="hide-for-small-only">
  <!-- 'hide-for-small-only' is a utility class for the foundation 6 framework which only displays on view ports larger than small -->
  
  <div class="" style="max-width: 100%;overflow-x: auto;" >
    <!-- The 'large view' table is wrapped in a horizontally scrollable div. This accounts for any edge cases where the table is wider than the container, but the small view port hasn't been triggered yet. -->
    <table>
      <thead>
        <tr>
          <th>Title</th>
          <th>Post Date</th>
          <th>Post Status</th>
          <th>Post Type</th>
          <th>Featured Image</th>
        </tr>
      </thead>
      <tbody>
        <?php
          if ( $post_query->have_posts() ) {
            while ( $post_query->have_posts() ) {
              $post_query->the_post();
              ?>
                <tr>
                  <td>
                    <?php the_title(); ?>
                  </td>
                  <td>
                    <?php the_Date(); ?>
                  </td>
                  <td>
                    <?php echo get_post_status(); ?>
                  </td>
                  <td>
                    <?php echo get_post_type(); ?>
                  </td>
                  <td>
                    <?php the_post_thumbnail(); ?>
                  </td>
                </tr>
              <?php
            }
          } else {
            ?>
              <tr>
                <td colspan="6" >
                  No posts to display.
                </td>
              </tr>
            <?php
          }
        ?>          
      </tbody>
    </table>
  </div>
  <?php
    wp_reset_query();
  ?>
</div>

And here is the output it produces in this table about Web Rockstar posts. Try resizing the window to see the responsiveness in action:

Responsive Table

Officially A WordPress Core Contributor
Post Date November 19, 2017
Post Status publish
Post Type post
Featured Image
WP Notes Widget PRO Launched
Post Date November 1, 2017
Post Status publish
Post Type post
Featured Image
Responsive HTML Tables
Post Date October 7, 2017
Post Status publish
Post Type post
Featured Image
Coming Soon – WP Note Widget PRO!
Post Date September 8, 2017
Post Status publish
Post Type post
Featured Image
RegEx for North American Phone Number
Post Date August 30, 2017
Post Status publish
Post Type post
Featured Image
Title Post Date Post Status Post Type Featured Image
Officially A WordPress Core Contributor November 19, 2017 publish post
WP Notes Widget PRO Launched November 1, 2017 publish post
Responsive HTML Tables October 7, 2017 publish post
Coming Soon – WP Note Widget PRO! September 8, 2017 publish post
RegEx for North American Phone Number August 30, 2017 publish post

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>