Make readable table headers with CSS
Tags: css, responsive, tables, html
Published: 2020-05-28 10:12:29

[Originally posted on my blog](https://www.1thingaweek.com/week/132/css-responsive-tables-readable-headers)

One thing I've always found tough to work with when it comes to responsive design is tables. Collapsing them on mobile is easy enough, but for data rich content you end up with stacked headers that don't provide the context you'd get on desktop.

* [Accessible, simple, responsive tables from CSS-Tricks](https://css-tricks.com/accessible-simple-responsive-tables/) (works for pricing or comparison data)
* ["Responsive" tables](https://www.w3schools.com/howto/howto_css_table_responsive.asp) from W3Schools (no re-flow for better readability, just introduces a scrollbar)
* [Simple Responsive Tables](https://allthingssmitty.com/2016/10/03/responsive-table-layout/) by Matt Smith is my favourite of the other solutions I've seen by using the `data` attribute, every row is treated to appear like it has it's own header (introduces a lot of duplication)

So there are some solutions, but for long sets of tabular data, either it introduces more text to read or they're not really what I would consider truly responsive. But I recently had a light bulb moment after looking at the [new calendar view](https://www.1thingaweek.com/calendar) for my website. Why not? concatenate the header content into a readable sentence? It would give an indication of what is in each row without having to repeat the content or introducing a horizontal scrollbar.

![Traditional responsive table layout](https://dev-to-uploads.s3.amazonaws.com/i/yjztt7c89vxt5rvs6xmd.jpg)

Either by using JavaScript or revealing the right header at different break points, we could reveal a row that has the column titles bunched up together which would stack really nicely. This isn't that readable though and using JavaScript is an overhead that isn't required.

![Improved responsive table layout](https://dev-to-uploads.s3.amazonaws.com/i/akjssobcpgsuty7erq78.jpg)

How do you make responsive headers more readable?
Let's take it from just a list of words

![Ultimate responsive table layout](https://dev-to-uploads.s3.amazonaws.com/i/6gwxf3ymayapktnzawnm.jpg)

The solution isn't difficult, it's just about understanding the flexbox model and how pseudo elements work. By combining the two, we can easily chain the headers into a readable header like the example above. Here's the basic CSS you would need to achieve this:

    /* Use flexbox to remove the headers from their columns */
    table thead tr,
    table tbody:first-child tr:first-child {
        display: flex;
        text-align: left;
    }
    /* Remove the right border from all but the last cell */
    table thead tr th:not(:last-child),
    table tr:first-child th:not(:last-child) {
        border-right: 0;
    }
    /* Let the last cell take up all of the available space, bringing all the content next to each other */
    table thead tr th:last-child,
    table tr:first-child th:last-child {
        flex: 1;
    }
    /* Remove any LEFT padding from all except the first cell */
    table thead tr th:not(:first-child),
    table tr:first-child th:not(:first-child) {
        padding-left: 0;
    }
    /* Remove any RIGHT padding from all except the last cell */
    table thead tr th:not(:last-child),
    table tr:first-child th:not(:last-child) {
        padding-right: 0;
    }
    /* Add a comma and a space before to all but the first cell */
    table thead tr th:not(:first-child):before,
    table tr:first-child th:not(:first-child):before {
        content: ',\00a0';
    }
    /* Add ' & ' before the last cell */
    table thead tr th:last-child:before,
    table tr:first-child th:last-child:before {
        content: '\00a0\0026\00a0';
    }

I've created a more complex solution as a [gist](https://gist.github.com/cchana/f403b367629644e9814308bc636f461a) on GitHub that has the basic HTML and the CSS to remove white space and introduce an alternating background colour to make the table easier to scan. You should be able to lift the CSS and apply it to any table. There's a resizable demo I've added to [JSFiddle](https://jsfiddle.net/cchana/mg15j7fs/2/) so you can try it out there too.

Even if you don't use the &lt;tbody&gt; HTML tags, looks like all browsers inject it anyway. By default, the code is wrapped in a media query which means it only applies to screens less than 700px wide. Either remove that restriction or adjust it to whatever your needs are.