--- title: Making Tables Responsive With Minimal CSS date: 2019-06-11 00:00:00 Z layout: post description: Learn how to easily implement responsive table layouts with only CSS summary: Building responsive tables can often become a nightmare. Learn how to easily implement responsive table layouts with only CSS. redirect_from: "/2019/06/11/responsive-tables/" featured: true --- Update (Oct 2019): @aardrian wrote a previous post about how changing the display properties on tables can impact screen readers. I highly recommend his excellent article Tables, CSS Display Properties, and ARIA --- *I find that the need to create responsive table layouts* pops up far more often than most developers would expect. The gut reaction might to be implement some sort of custom grid-system or pull in a pre-built library. Don't do this - just use tables and some simple CSS. My recent article, [Write HTML Like It's 1999](/blog/html-like-1999), received far more attention than I ever expected on HackerNews. With this attention came a few comments mentioning how `table` elements don't play nice with mobile devices or that it's not possible to have a useable layout on smaller screens. *This simply isn't true*. Included below are two separate demos showing how to optimize `table` HTML for mobile devices using only a minimal amount of CSS. These implementations may not be perfect, but they are far superior to injecting a bunch of custom `div` elements to *look* like tables. ## Demo 1: Just let them scroll Okay I will admit, this implementation isn't the *greatest* but I find it does work well with huge datasets. Simply set a `min-width` on your parent `table` element and the browser will just require the user to scroll the contents horizontally. ```css table { min-width: 800px; /* Set your desired min-width here */ } ``` Check out the CodePen below to see it in action:

See the Pen Responsive Tables #1: Horizontal Scrolling by Bradley Taunt (@bradleytaunt) on CodePen.

I actually prefer this method because of its simplicity and function. Users on mobile are familiar with scrolling since it is one of the most basic actions required. Seeing a "cut-off" table gives them an instant visual cue that they have the ability to scroll the content. ## Demo 2: More flexible than you think Using something like `flexbox` tends to work better when you are working with smaller table datasets. All you need to do is add some minor `flexbox` layout at your targeted mobile screen size. ```css /* Using 800px as mobile screen in this example */ @media(max-width: 800px) { /* Hide the table headings */ table thead { left: -9999px; position: absolute; visibility: hidden; } table tr { border-bottom: 0; display: flex; flex-direction: row; flex-wrap: wrap; margin-bottom: 40px; } table td { border: 1px solid; margin: 0 -1px -1px 0; /* Removes double-borders */ width: 50%; } } ``` Check out the CodePen demo below:

See the Pen Responsive Tables #2: Flexbox by Bradley Taunt (@bradleytaunt) on CodePen.

There are some caveats with this approach: 1. We currently hide the `thead` row when in mobile view (only visually - screen readers can still scan it) 2. Some more custom work might be needed depending on how many items per `flexbox` row makes sense (based on project and dataset) You could keep the table headings and style them the same as the `tbody` contents, but I find hiding them a little cleaner. That choice is entirely up to your personal preference. You can also decide to add heading `span` elements inside the main `tbody` elements like so: ```css /* Default span styling - hidden on desktop */ table td span { background: #eee; color: dimgrey; display: none; font-size: 10px; font-weight: bold; padding: 5px; position: absolute; text-transform: uppercase; top: 0; left: 0; } /* Simple CSS for flexbox table on mobile */ @media(max-width: 800px) { table thead { left: -9999px; position: absolute; visibility: hidden; } table tr { border-bottom: 0; display: flex; flex-direction: row; flex-wrap: wrap; margin-bottom: 40px; } table td { border: 1px solid; margin: 0 -1px -1px 0; padding-top: 35px; /* additional padding to avoid heading overlap */ position: relative; width: 50%; } /* Show the heading span */ table td span { display: block; } } ```

See the Pen Responsive Tables #2.5: Flexbox by Bradley Taunt (@bradleytaunt) on CodePen.

**Updated**: As pointed out by user [mmoez](https://news.ycombinator.com/user?id=mmoez), it is far less repetitive to use `:nth-child` pseudo selectors to implement the heading fields on mobile (as outlined in this [CSS-Tricks article](https://css-tricks.com/responsive-data-tables/)). ## Why should I care to use `table` elements? Simply put: **accessibility** and **proper semantics**. Why use a screwdriver when you need a hammer? Sure, you can make that screwdriver look and *almost* work the same as a hammer, but for what purpose? Just use the damn hammer[^1]. Have fun making your tables responsive! [^1]: I know, this is a terrible analogy... * footnotes will be placed here. This line is necessary {:footnotes}