Table scrolling horizontally and vertically

Hi all

Sorry I don’t have any code, I’m struggling on where to start.

I want to create a table something lihe this.

The number of Teams and Contacts will grow but I’m limited for space so the table will have to scroll.

When the number of teams grows I will scroll to the left to see the teams but I dont want the whole of the table to scroll.

I want to keep the contacts where they are and just scroll the teams, sort of underneath the contacts.

When the contacts increase I will scroll down but I want to keep the column headers (Name, Position and Teams)in place.

When I scroll down I need the Contacts and Teams to scroll together obviously.

I’m sure I could do either of these things but is it possible to do both and does anyone know the best way to build something like this.

I know this is table like but I think it would be better to build this from div’s and not an actual html table

1 Like

Actually a table is the right tool for the job semantically as this is tabular data and divs would not be semantically correct. However, I’m not sure this can be accomplished neatly anyway,

What you are asking for is very tricky indeed and does depend on the criteria for the table also.

A possible but non semantic solution would be to use separate tables for the fixed headers and fixed side columns and a separate table for just the content. This means that all cells would need to be a fixed height and width otherwise the disparate tables won’t match. This old example shows the basis for a sideways scroll but I’m not sure how easy it would be to tie in a vertical scroll also. It might get very complicated.

If you want fluid cells dependent on the width of the content then it gets very difficult indeed because the fixed headers need to be part of the same table and making them fixed becomes almost impossible (here’s a very very old example of vertical scrolling in a fluid table but is a bit limited in its use).

In light of the above problems you may be better off looking for a script that will automatically convert the headers to fixed.

1 Like

I’ve changed now so the table only need to scroll vertically like in your first example.

I think I’m going to do it with div’s as it’s easier to style and not a table but I’m using display table, row and cell.

My problem now is I need space between the rows but I cant do margin with display: table; or row or cell.

I know I can do border-spacing but just need the margin on the bottom

That makes no sense. You have what is tabular data, you use divs instead of table elements, then use css to style the divs to behave and appear like table elements. :upside_down:
How about use a table?


If you are using table-row and table-cell then it’s not much different to using a proper table :slight_smile:

If you want space between the rows then you owuld do it the same as you would with a table and use the border spacing property on the display:table element or padding on the cells.

Here’s a demo of a simple scroll using a table.

It uses the table-layout:fixed algorithm so that cells remain the same size.

1 Like

The only thing I could think of that would work would involve shifting the overflow columns to display beneath the columns that “fit” and increasing the rowspan of the contact columns cells to accommodate the number of nested rows.

I have a strong feeling implementing that approach would be complex and messy, but I am often amazed at what flexbox can do, so maybe not.

I know I should use a table.

Whats the best way to add a margin to the bottom of a row, using a colored border doesn’t seem like the best way.

I only want a bottom margin or to be able to take off the top or bottom spacing on the first or last row in the table.


It’s a little bit unclear (to me) as to what you want to achieve but you have a couple of options.

  1. Border-spacing on the table element will supply a vertical (or horizontal or both) spacing between cells.


table{border-spacing:0 10px}

That will apply a 10px gap above and below the cell (outside the border of a cell if border has been set).

  1. You could add padding top or bottom or both as required to the cell itself to make spacing.

td {padding:10px 0}

That will make 10px top and bottom padding on the cell (inside the border of a cell if border has been set).

You have to remember that table-cells cannot have margins because cells are intrinsically connected to each other and cannot be moved with margins. You can make space between borders (in the border-collapse separate model) by using border-spacing as shown. If you have collapsed the borders then you can’t use border-spacing.

To make space inside the cell you use padding.

Either of the above will allow you to make space either inside or outside the cell.

What I need is something like this, This is the best example I have found.

I need a table with a left column that is fixed and the rest will scroll.

My last problem is the height of the rows in the two tables like here where the row on the left is taller and then they don’t match.

The Responsive Web Design community has been hard at work on making tables fit small screens (or large tables fit desktop). Here are a quite a few ideas put forth:

I showed you a similar example in my very first post :slight_smile:

Yes as I mentioned before you can’t do that with separate tables (or divs) because they will have no relationship with each other. You would need to set a height on the cells to keep them the same height and perhaps hide the overflow.

The other options as mentioned would be to resort to a script to achieve this.

1 Like

Ok, here’s a single table version with horizontal scroll that uses one line of jquery to create the fixed side column.

I’ve only just knocked this up a few minutes ago so needs testing.

It also assumes that you won’t be having form fields or the like in the cells because the way this works is that the table is cloned and then positioned on top of the original table with absolute positioning. The original table is in a div that allows the table to scroll horizontally while the cloned div is placed out of that context and does not scroll.

The cells in the cloned table are hidden with css except for the first column. That allows the illusion of a fixed first column.


I played a bit with the Codepen table @PaulOB posted above. :slight_smile:
My test was to try to replace the table cloning with some absolute positioned pseudo elements duplicating the header cells in each row with attr data content from the html.

I think maybe this test version can work as you want. Please try it out and see if you could adapt it to your need.

I did test this in Firefox ESR 45.9.0 and Chromium 58.0.3029.81, both are Linux versions. There are some differences between them, mostly the column calculation I think, but with some finetuning at least this experiment seems to be stable.

Table-Horizontal-Scroll.html (4.1 KB)

Here’s a JsFiddle you can play with: :slight_smile:

1 Like


I found an old demo (2012) also using block display for scrolling but in a horizontal reordering of the table at narrow widths:

It’s responsive in that it is, in narrower viewports, displaying all the rows as columns starting with the thead fixed to the left and the rest is horizontally scrolling. Mind though that this method can’t handle multiple content lines in any cell.

@RachelR, For a responsive solution, maybe that method could be of use here? :slight_smile:

1 Like

Yes that’s a nice demo:)

That’s the problem with most of those methods which is why I went for the cloned table approach as it will handle multiple lines in cells and fluid width cells if required and still maintain integrity between both.

It’s a similar problem when you do the vertical scroll and in a fluid layout it becomes tricky to match the non scrolling header with the content below and compromises have to be made.

Originally Firefox used to allow just setting tbody to a height and overflow:scroll and it would work to keep the headers fixed. I don’t know why that was never implemented as a standard because it is exactly what we wanted.

I think the scrolling table was also required for larger viewports as space was limited for the table and the number of teams (cells) was likely to grow and grow.

1 Like

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