Making tables responsive is difficult from a user-experience and implementation perspective. First I’ll outline the main solutions out there and then provide the solution that I came to.



You could just let the cell contents wrap around. This is very content dependent and your minimum column width will be determined by the largest element that can’t be wrapped. This could be a long word with no spaces or some kind of control. A related approach is to set a max-width on the content with text-overflow: ellipsis to truncate the content. You probably want to set the title attribute on that element so that the user can still get the full content if they need it.


  • Technically simple.


  • Won’t work with some content types (e.g. form controls, …).
  • Have to duplicate text content in a title attribute to allow the user to still access it.
  • Tedious to decorate each cell with a class defining its max width.

Scrollable Table

You could make the table scroll. Scrolling horizontally when you have a header across the top isn’t hard to do. You just wrap the whole table in a scrollable element and your done. However it is rather inconvenient that you can’t see all of the columns, particularly if there is an action column or you have filters on the column level.

Scrolling vertically gets a bit trickier since you probably want to lock the table header. Whatever you do for locking will probably break the auto-sizing of the columns and create a bigger problem than you had before.


  • Technically simple.
  • Simple to implement.
  • All data is visible.


  • Can’t see data for all columns at once.
  • If you have an “actions” column then it is harder to correlate with the entity you are performing the action on.
  • Row/Column locking may be required and be painful to implement.

Show/Hide Columns

You could start by just showing the most important columns and then show additional ones as space becomes available. This follows the principle of progressive enhancement where you start with the most vital information being visible and then you show more as space allows. One problem is that you have to make the decision for the user about what they want to see. You might get that wrong. If you are considerate then you at least have a column toggle dropdown where the user can add/remove columns manually. But then you have to deal with them adding more columns than you can view on the page and you need another solution for that.

Another issue is that you may actually have more vital data to display than you have room for. Another issue is that if you have a column filter on a hidden column then you can get confused as to why data isn’t showing up depending on how your filters are displayed.


  • Important data is visible.


  • May hide filters.
  • May hide relevant data.
  • May not be able to fit columns for all required vital data.


At some point you just say, “I HATE TABLES” and you throw them out completely. So you take your data and pivot it turning each row into a card with the column headings as labels. It provides the maximum amount of space to display your content so that you don’t have to truncate it and you can keep all of your columns. The main problem is that it takes up a lot of vertical space so you will be scrolling for days. Also, depending on your filtering mechanism, your filter values might be out of view so that they are hard to interact with or you don’t realize that your data is filtered.


  • Can see all data.


  • Filters and bulk actions may be hard to use.
  • Hard to relate rows to each-other.
  • Scrolling for days.


A hybrid of the scroll and card solutions involves flipping the table so that the column headers are now the first row and each row is now a column. Then you make the columns scroll horizontally while locking the first column. Locking the first column however will take it out of the size calculations for the rest of the rows so your rows could look like a split-level house if you don’t take precations.


  • Can see all data.
  • Data is still correlated by row and column.
  • Takes up similar vertical space as a table.


  • Locking a column (header column) makes multi-line rows hard.

My Solution

I really like the Flip solution from a UX perspective. It gives you access to all of your data in a contextual way. To solve the multi-line problem I combo it with the Squash solution so that all cells are only single-line when the table is flipped. The beautiful thing is that you can do it all with CSS without the assistance of JavaScript!

To facilitate this solution I put together some utility classes.

Max Text

The first set of utility classes has to do with setting a max width of a cell and truncating the content with an ellipsis. This is really just to allow me to prevent long columns from taking over the page when the table isn’t flipped. This simply involves setting the following css properties:

.some-class {
  max-width: <some-value>;
  overflow: hidden;
  text-overflow: ellipsis; 

The utility class takes the form of .max-{break}-{size} where {break} is the breakpoint and {size} is the relative size.

The following table explains the breakpoint options:

  Extra Small
< 576px
≥ 576px
≥ 768px
≥ 992px
Extra Large
≥ 1200px
Class prefix .max-{#} .max-sm-{#} .max-md-{#} .max-lg-{#} .max-xl-{#}

The following table explains the sizing options:

Size 1 2 3 4 5
Value 5vw 10vw 15vw 20vw 25vw

I decided to use view width (vw) units but you could easily modify it for whatever you like.

Table Flip

The second set of utility classes has to do with pivoting the table. The css is a bit more involved. The class names take the form of .table-flip-{break} where {break} is the breakpoint.

≤ 767px
≤ 991px
≤ 1199px
Extra Large
Class prefix .table-flip-sm .table-flip-md .table-flip-lg .table-flip-xl

When the table flips it will set the max width of a cell to 100% and truncate after that. It does this to prevent wrapping.


The following example contains the code for the utilities. When using them together you probably want to use a max text breakpoint that is a level higher than the table flip breakpoint. This is so that the max text styles aren’t applied to the table flip. The table flip has its own styles that take care of truncating content and you probably want to view as much of a pivoted row as possible.

  1. CSS
  2. Responsive

Erik Murphy

Erik Murphy

Erik is an agile software developer in Charlotte, NC. He enjoys working full-stack (CSS, JS, C#, SQL) as each layer presents new challenges. His experience involves a variety of applications ranging from developing brochure sites to high-performance streaming applications. He has worked in many domains including military, healthcare, finance, and energy.