skip to Main Content

I have been working on a piece of code for several hours now, trying to achieve the desired layout for a table. However, every time I make adjustments to the code, it causes the table to become distorted or behave unexpectedly. My goal is to have a scrollbar that appears only for the scrollable content within the table, not for the entire table itself. Additionally, I want the scrollbar to be positioned specifically at the bottom of the scrollable content area.

Kindly help me on this one. Thank youuu!

.table-scroll {
  position: relative;
  width: 100%;
  z-index: 1;
  margin: auto;
  height: 50vh;
  width: 1000px;
}

.table-scroll table {
  width: 100%;
  margin: auto;
  border-collapse: separate;
  border-spacing: 0;
}

.table-scroll th,
.table-scroll td {
  padding: 5px 10px;
  border: 1px solid #000;
  background: #fff;
  vertical-align: top;
  text-align: center;
}

.table-scroll thead th {
  background: #333;
  color: #fff;
  top: 0;
  z-index: 1;
}

th.sticky-left,
td.sticky-left {
  position: -webkit-sticky;
  position: sticky;
  left: 0;
  z-index: 4;
  background: #ccc;
}

th.sticky-left:nth-child(2),
td.sticky-left:nth-child(2) {
  position: -webkit-sticky;
  position: sticky;
  left: 70px;
  z-index: 10;
  background: #ccc;
}

th.sticky-right,
td.sticky-right {
  position: -webkit-sticky;
  position: sticky;
  right: 0;
  z-index: 4;
  background: #ccc;
}
<div class="table-scroll">
    <table border="1">
      <thead>
        <tr>
          <th class="sticky-left w-32" rowspan="2">DATE</th>
          <th class="sticky-left w-32" rowspan="2">DATE2</th>
          <th colspan="10">LINE 1</th>
          <th colspan="10">LINE 2</th>

          <th class="sticky-right" rowspan="2">LINE 3</th>
        </tr>
        <tr>
          <th>SENSOR 1</th>
          <th>SENSOR 2</th>
          <th>SENSOR 3</th>
          <th>SENSOR 4</th>
          <th>SENSOR 5</th>
          <th>SENSOR 6</th>
          <th>SENSOR 7</th>
          <th>SENSOR 8</th>
          <th>SENSOR 9</th>
          <th>SENSOR 10</th>
          <th>SENSOR 1</th>
          <th>SENSOR 2</th>
          <th>SENSOR 3</th>
          <th>SENSOR 4</th>
          <th>SENSOR 5</th>
          <th>SENSOR 6</th>
          <th>SENSOR 7</th>
          <th>SENSOR 8</th>
          <th>SENSOR 9</th>
          <th>SENSOR 10</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td class="sticky-left w-32">VALUE 1</td>
          <td class="sticky-left w-32">VALUE 1</td>
          <td>SENSOR DATA 1</td>
          <td>SENSOR DATA 2</td>
          <td>SENSOR DATA 3</td>
          <td>SENSOR DATA 4</td>
          <td>SENSOR DATA 5</td>
          <td>SENSOR DATA 6</td>
          <td>SENSOR DATA 7</td>
          <td>SENSOR DATA 8</td>
          <td>SENSOR DATA 9</td>
          <td>SENSOR DATA 10</td>
          <td>SENSOR DATA 1</td>
          <td>SENSOR DATA 2</td>
          <td>SENSOR DATA 3</td>
          <td>SENSOR DATA 4</td>
          <td>SENSOR DATA 5</td>
          <td>SENSOR DATA 6</td>
          <td>SENSOR DATA 7</td>
          <td>SENSOR DATA 8</td>
          <td>SENSOR DATA 9</td>
          <td>SENSOR DATA 10</td>
          <td class="sticky-right">VALUE 1</td>
        </tr>
        <tr>
          <td class="sticky-left w-32">VALUE 2</td>
          <td class="sticky-left w-32">VALUE 2</td>
          <td>SENSOR DATA 1</td>
          <td>SENSOR DATA 2</td>
          <td>SENSOR DATA 3</td>
          <td>SENSOR DATA 4</td>
          <td>SENSOR DATA 5</td>
          <td>SENSOR DATA 6</td>
          <td>SENSOR DATA 7</td>
          <td>SENSOR DATA 8</td>
          <td>SENSOR DATA 9</td>
          <td>SENSOR DATA 10</td>
          <td>SENSOR DATA 1</td>
          <td>SENSOR DATA 2</td>
          <td>SENSOR DATA 3</td>
          <td>SENSOR DATA 4</td>
          <td>SENSOR DATA 5</td>
          <td>SENSOR DATA 6</td>
          <td>SENSOR DATA 7</td>
          <td>SENSOR DATA 8</td>
          <td>SENSOR DATA 9</td>
          <td>SENSOR DATA 10</td>
          <td class="sticky-right">VALUE 2</td>
        </tr>
        <tr>
          <td class="sticky-left w-32">VALUE 1</td>
          <td class="sticky-left w-32">VALUE 1</td>
          <td>SENSOR DATA 1</td>
          <td>SENSOR DATA 2</td>
          <td>SENSOR DATA 3</td>
          <td>SENSOR DATA 4</td>
          <td>SENSOR DATA 5</td>
          <td>SENSOR DATA 6</td>
          <td>SENSOR DATA 7</td>
          <td>SENSOR DATA 8</td>
          <td>SENSOR DATA 9</td>
          <td>SENSOR DATA 10</td>
          <td>SENSOR DATA 1</td>
          <td>SENSOR DATA 2</td>
          <td>SENSOR DATA 3</td>
          <td>SENSOR DATA 4</td>
          <td>SENSOR DATA 5</td>
          <td>SENSOR DATA 6</td>
          <td>SENSOR DATA 7</td>
          <td>SENSOR DATA 8</td>
          <td>SENSOR DATA 9</td>
          <td>SENSOR DATA 10</td>
          <td class="sticky-right">VALUE 1</td>
        </tr>
      </tbody>
    </table>
  </div>

2

Answers


  1. Wrap the <table> in a block level element (ex. <div>, <section>, <p>, etc…) and as an option you can assign overflow-x: scroll to the block element which makes the scrollbar always present whether it’s actually needed or not. I prefer scroll because it doesn’t create shifting like the default value of auto when it pops in and out. Basically any block element can be scrollable and an inline-block element can be scrollable as well if it is styled with white-space: nowrap. Read this post for further details concerning what’s scrollable. What’s not scrollable are <table>s and their associated children elements.

    The example below consists of 3 <table>s each wrapped in a block element (<section>) The first and last <table> are a single column with a <thead>/<tr>/</th> and 3 <tr><th></th></tr> in the <tbody>. They are the "sticky" elements (more like "fixed", see comments in example). The middle <table> (aka table.content) contains the scrollable content witch consists of 20 columns and, when including the <thead>, 4 rows . Note the scrollbar directly under table.content but not under table.lead or table.last👍. This layout is very responsive (not designed for mobile though) view it in Full page mode. Further details are commented in the example.

    /*
      All lengths in rem units reference the font-size of <html>
      (aka :root). The CSS clap() function has a minimum of 1rem, 
      a maximum of 3rem, and a formula which dynamically changes
      as the viewport width changes because of the 8vw.
    */
    :root {
      font-size: clamp(1rem, 8vw - 2rem, 3rem); 
      line-height: 1.2;
      font-family: Consolas;
    }
    
    /*
      Flex container keeps the 3 <section>s inline.
    */
    main {
      display: flex;
    }
    
    /*
      table-layout: fixed makes <table> honor widths set directly
      on any of it's <td> or <th>.
    */
    table {
      table-layout: fixed; 
      border-collapse: collapsed;
      border-spacing: 0;
    }
    
    table,
    th,
    td {
      border: 1.51515px groove rgb(128 128 128);
    }
    
    th,
    td {
      width: 2.5rem;
      padding: 5px;
      line-height: 2;
      text-align: center;
    }
    
    th {
      background: rgb(183, 183, 183);
    }
    
    /*
      Applied to the first column: table.lead and the last column: 
      table.last which takes them out of normal document flow when
      at their designated position (for table.lead it's left: 0 
      and table.last it's right: 0). Notice that the .fixed
      <table>s don't move? The reason why is because they have no 
      sibling elements -- I isolated them by wrapping each in a 
      <section> so now they behave like a fixed element without the 
      limitation of referencing the viewport.
      */
    .fixed {
      position: sticky;
    }
    
    .lead {
      left: 0;
    }
    
    .last {
      right: 0;
    }
    
    .scroll {
      max-width: 100vw;
      overflow-x: scroll;
    }
    
    .content {
      width: max-content;
    }
    <main>
      <section>
        <table class="fixed lead">
          <thead>
            <tr><th>COL01</th></tr>
          </thead>
          <tbody>
            <tr><th>ROW01</th></tr>
            <tr><th>ROW02</th></tr>
            <tr><th>ROW03</th></tr>
          </tbody>
        </table>
      </section>
      <section class="scroll">
        <table class="content">
          <thead>
            <tr>
              <th>COL02</th><th>COL03</th>
              <th>COL04</th><th>COL05</th>
              <th>COL06</th><th>COL07</th>
              <th>COL08</th><th>COL09</th>
              <th>COL10</th><th>COL11</th>
              <th>COL12</th><th>COL13</th>
              <th>COL14</th><th>COL15</th>
              <th>COL16</th><th>COL17</th>
              <th>COL18</th><th>COL19</th>
              <th>COL20</th><th>COL21</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
            </tr>
            <tr>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
            </tr>
            <tr>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
              <td>DATA</td><td>DATA</td>
            </tr>
          </tbody>
        </table>
      </section>
      <section>
        <table class="fixed last">
          <thead>
            <tr><th>COL22</th></tr>
          </thead>
          <tbody>
            <tr><th>ROW01</th></tr>
            <tr><th>ROW02</th></tr>
            <tr><th>ROW03</th></tr>
          </tbody>
        </table>
      </section>
    </main>
    Login or Signup to reply.
  2. You can achieve the said requirement by using position: sticky;.

    You can refer the following example.

    table {
      font-family: "Fraunces", serif;
      font-size: 125%;
      white-space: nowrap;
      margin: 0;
      border: none;
      border-collapse: separate;
      border-spacing: 0;
      table-layout: fixed;
      border: 1px solid black;
    }
    table td,
    table th {
      border: 1px solid black;
      padding: 0.5rem 1rem;
    }
    table thead th {
      padding: 3px;
      position: sticky;
      top: 0;
      z-index: 1;
      width: 25vw;
      background: white;
      color: #fff;
      background: #333;
    }
    table td {
      background: #fff;
      padding: 4px 5px;
      text-align: center;
    }
    
    table tbody th {
      font-weight: 100;
      font-style: italic;
      text-align: left;
      position: relative;
    }
    table thead th:first-child {
      position: sticky;
      left: 0;
      z-index: 2;
      color: #fff;
      background: #333;
    }
    table tbody tr td:first-child {
      position: sticky;
      left: 0;
      background: white;
      z-index: 1;
      color: #fff;
      background: #333;
    }
    
    table thead th:last-child {
      position: sticky;
      right: 0;
      z-index: 2;
      color: #fff;
      background: #333;
    }
    table tbody tr td:last-child {
      position: sticky;
      right: 0;
      background: white;
      z-index: 1;
      color: #fff;
      background: #333;
    }
    caption {
      text-align: left;
      padding: 0.25rem;
      position: sticky;
      left: 0;
    }
    <main>
      <table>
        <thead>
          <tr>
            <th>COL02</th>
            <th>COL03</th>
            <th>COL04</th>
            <th>COL05</th>
            <th>COL06</th>
            <th>COL07</th>
            <th>COL08</th>
            <th>COL09</th>
            <th>COL10</th>
            <th>COL11</th>
            <th>COL12</th>
            <th>COL13</th>
            <th>COL14</th>
            <th>COL15</th>
            <th>COL16</th>
            <th>COL17</th>
            <th>COL18</th>
            <th>COL19</th>
            <th>COL20</th>
            <th>COL21</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
          </tr>
          <tr>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
          </tr>
          <tr>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
            <td>DATA</td>
          </tr>
        </tbody>
      </table>
    </main>

    Hope this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search