0

I am trying to create a page layout where I render:

  • A fixed width side bar
  • A main content section with
    • A header row (title + button)
    • A table

The table may hold quite a few columns and I don't want them to get squished together. Instead, I would like the table to scroll horizontally. However, what ends up happening is that the table expands its container and creates a horizontal scroll on the main layout. The scrollbar doesn't show up in the table itself.

You can see the code and the problem in action here:

.App {
  display: flex;
  flex-direction: row;
  width: 100%;
}

.Sidebar {
  display: block;
  width: 150px;
  background-color: red;
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: 150px;
}

.Main {
  display: flex;
  flex-direction: column;
  width: 100%;
  background-color: green;
}

.TitleBar {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.TableContainer {
  width: 100%;
  position: relative;
  overflow-x: scroll;
}

.Table {
  width: 100%;
  table-layout: auto;
}
<div class="App">
  <div class="Sidebar">Sidebar</div>
  <main class="Main">
    <div class="TitleBar">
      <div>Title</div>
      <div>
        <button>Create</button>
      </div>
    </div>
    <div class="TableContainer">
      <table class="Table">
        <thead>
          <tr>
            <th>Name</th>
            <th>Prop 1</th>
            <th>Prop 2</th>
            <th>Prop 3</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Item 1</td>
            <td>Value 1.a</td>
            <td>Value 1.b</td>
            <td>Value 1.c</td>
            <td>
              <button>Edit</button>
            </td>
          </tr>
          <tr>
            <td>Item 2</td>
            <td>Value 2.a</td>
            <td>Value 2.b</td>
            <td>Value 2.c</td>
            <td>
              <button>Edit</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </main>
</div>
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
David Saltares
  • 808
  • 2
  • 11
  • 19
  • Does this answer your question? [How do I create an HTML table with a fixed/frozen left column and a scrollable body?](https://stackoverflow.com/questions/1312236/how-do-i-create-an-html-table-with-a-fixed-frozen-left-column-and-a-scrollable-b) – Heretic Monkey Oct 31 '22 at 14:21

3 Answers3

1

First set your table to display: block then set overflow-x: auto

.Table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
}

As you are saying the rows squash together when going into responsive view. You can prevent that by giving the TD and the TH elements a min-width to not collapse further then the limit.

This method works. See snippet down below:

Note: I added a td min-width so they don't shrink down responsively to show how it works.

body {
  margin: 0;
}

.App {
  display: flex;
  flex-direction: row;
  width: 100vw;
}

.Sidebar {
  display: block;
  width: 100px;
  background-color: red;
  flex-grow: 0;
  flex-shrink: 0;
}

.Main {
  display: flex;
  flex-direction: column;
    width: calc(100% - 100px);

  background-color: green;
}

.TitleBar {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.TableContainer {
  position: relative;
}

td {
  min-width: 500px;
}

.Table {
  display: block;
  overflow-x: auto;
  white-space: nowrap;
}
<div class="App">
  <div class="Sidebar">Sidebar</div>
  <main class="Main">
    <div class="TitleBar">
      <div>Title</div>
      <div>
        <button>Create</button>
      </div>
    </div>
    <div class="TableContainer">
      <table class="Table">
        <thead>
          <tr>
            <th>Name</th>
            <th>Prop 1</th>
            <th>Prop 2</th>
            <th>Prop 3</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Item 1</td>
            <td>Value 1.a</td>
            <td>Value 1.b</td>
            <td>Value 1.c</td>
            <td>
              <button>Edit</button>
            </td>
          </tr>
          <tr>
            <td>Item 2</td>
            <td>Value 2.a</td>
            <td>Value 2.b</td>
            <td>Value 2.c</td>
            <td>
              <button>Edit</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </main>
</div>

JS Fiddle

Hosted example by me:

FUZIION
  • 1,606
  • 1
  • 6
  • 19
  • Thanks, but that doesn't solve the problem either. The `.Main` container scrolls as a whole. See it here: https://jsfiddle.net/dsaltares/egf7238z/14/. – David Saltares Oct 31 '22 at 13:14
  • Add it to the table not the .main container – FUZIION Oct 31 '22 at 13:16
  • Edited answer, inserted a snippet showing the scroll. – FUZIION Oct 31 '22 at 13:23
  • Still not quite right. See here: https://www.loom.com/share/9dfda5e551d24ccab3d890dbef9a8763. Now there is a scrollbar for the whole layout and a scrollbar inside the table. – David Saltares Oct 31 '22 at 13:32
  • that scrollbar is part of the snippet, insert it into your site and you'll see. – FUZIION Oct 31 '22 at 14:10
  • Added `width 100vw` on `.app`, `25% width` for sidebar and `75% width` for the tablewrapper to visualize this working as requested. To scroll the table you have to have your cursor on the table. – FUZIION Oct 31 '22 at 14:15
  • You can see the result better within this hosted example on my server. http://uploads.refuzion.nl/answers/question-74262942.html – FUZIION Oct 31 '22 at 14:24
  • Thanks for clarifying. The only problem is that my sidebar needs to be a fixed width in pixels. Do you know how to support that? – David Saltares Oct 31 '22 at 14:57
  • Yes, do this by simply setting a width for the sidebar (for example 100px) and then calculating the with of `.main` using `calc(100% - 100px)` 100px being the width of the sidebar. See snippet in the answer for implemented solution – FUZIION Oct 31 '22 at 15:04
0

Remove overflow-x: scroll from .TableContainer and add overflow-x: auto to .main class and try.

shotgun02
  • 756
  • 4
  • 14
  • Thanks but that doesn't work as it makes the `.TitleBar` scroll as well. I want to scroll *just* the table itself. See here: https://jsfiddle.net/dsaltares/egf7238z/9/. – David Saltares Oct 31 '22 at 13:03
0

One very simple way to fix this is you can add minimum width of table, You can not add a scroll in the table itself.

.Table {
  width: 100%;
  table-layout: auto;
  min-width:800px;
}
Avais
  • 58
  • 6