Search code examples
cssscrollpositioncss-gridsticky

Table using position:sticky and display: grid


I am trying to display data in a table-like view using display:grid and position: sticky to stick the first two header rows and the first three columns on each subsequent row.

The header rows stick properly, the first three columns in the rows however only stick for a little bit of the scroll then they scroll off to the left. What is causing this behaviour? Is this how sticky is supposed to work in this scenario?

:root {
  --column-width: 70px;
}

.wrapper {
  font-family: sans-serif;
  max-width: 700px;
  height: 300px;
  overflow: auto;
}

.table-container {
  width: auto;
}

.table {
  position: relative;
  display: grid;
  grid-template-columns: 200px repeat(14, var(--column-width));
}

.table.header {
  position: sticky;
  top: 0;
  z-index: 999;
}

.table.header+.table.header {
  position: sticky;
  top: 36px;
  ;
}

.table.header .row {
  background: #ccc !important;
}

.table .row.sticky {
  position: sticky;
  background: #eee;
}

.table .row.sticky:nth-child(1) {
  left: 0px;
}

.table .row.sticky:nth-child(2) {
  left: 200px;
}

.table .row.sticky:nth-child(3) {
  left: 270px;
}

input {
  width: 45px;
}
<div class="wrapper">

  <div class="table-container" role="table" aria-label="Destinations">
    <div class="table header" role="rowgroup">
      <div class="row sticky" role="columnheader">Produkt</div>
      <div class="row sticky" role="columnheader">föreg. År</div>
      <div class="row sticky" role="columnheader">Totalt produkt</div>
      <div class="row" role="columnheader">v.1</div>
      <div class="row" role="columnheader">v.2</div>
      <div class="row" role="columnheader">v.3</div>
      <div class="row" role="columnheader">v.4</div>
      <div class="row" role="columnheader">v.5</div>
      <div class="row" role="columnheader">v.6</div>
      <div class="row" role="columnheader">v.7</div>
      <div class="row" role="columnheader">v.8</div>
      <div class="row" role="columnheader">v.9</div>
      <div class="row" role="columnheader">v.10</div>
      <div class="row" role="columnheader">v.11</div>
      <div class="row" role="columnheader">v.12</div>
    </div>
    <div class="table header" role="rowgroup">
      <div class="row sticky" role="columnheader">Totalt vecla</div>
      <div class="row sticky" role="columnheader"></div>
      <div class="row sticky" role="columnheader"></div>
      <div class="row" role="columnheader">100 000 SEK</div>
      <div class="row" role="columnheader"></div>
      <div class="row" role="columnheader">100 000 SEK</div>
      <div class="row" role="columnheader"></div>
      <div class="row" role="columnheader"></div>
      <div class="row" role="columnheader">100 000 SEK</div>
      <div class="row" role="columnheader">100 000 SEK</div>
      <div class="row" role="columnheader"></div>
      <div class="row" role="columnheader">100 000 SEK</div>
      <div class="row" role="columnheader"></div>
      <div class="row" role="columnheader"></div>
      <div class="row" role="columnheader">100 000 SEK</div>
    </div>
    <div class="table row" role="rowgroup">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>
    <div class="table row" role="rowgroup">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>
    <div class="table row" role="rowgroup">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>
    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>
    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>
    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>

    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>

    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>

    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>

    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>

    <div class="table row">
      <div class="row sticky" role="columnheader">Produktnamn</div>
      <div class="row sticky" role="columnheader">100 000 SEK</div>
      <div class="row sticky" role="columnheader">50 000 SEK</div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
      <div class="row" role="columnheader"><input type="number" /></div>
    </div>
  </div>

</div>

EDIT

I edited the snippet since I realized if I put the max-width on .wrapper instead of on .table-container and then set .table-container to width: auto; it shows the left columns for longer. They still scroll out to the left at the end of the scroll as well as two of the columns wrapping over each other.


Solution

  • Let's start with how position:sticky works.

    When an element is sticky it is only stuck relative to it's parent, Meaning if the parent is scrolled away the sticky element will follow it.

    Demo

    [scoll] {
      background: pink;
      white-space: nowrap;
      padding: 10px;
      overflow: auto;
    }
    
    [stickyElementsContainer]{
      background: orange;
      width:200px;
      padding: 10px;
    }
    
    [stuckElement] {
      background: red;
      position: sticky;
      left: 0;
    }
    
    [overflow]{
      width:2000px;
      height:1px;
    }
    <div scoll>
      <div stickyElementsContainer>
        <span stuckElement>stuck</span>
      </div>
      <div overflow></div>
    </div>

    Now we understand that when an element goes out of the visible area, The sticky element inside it will follow it.


    Your issue is exactly the same, When you scroll the wrapper, The row is scrolled way, therefore the sticky elements inside follows it.

    But we can clearly see that the row is still wide, What is happening ?

    The following Demo should explain

    [scrollable] {
      width: 300px;
      padding: 10px;
      background: red;
      border: 5px solid;
      overflow:auto;
    }
    
    [container] {
      white-space: nowrap;
      background: orange;
      padding: 10px;
    }
    <div scrollable>
      <div container>
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
        in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      </div>
    </div>

    The orange <div> is your row, It takes the width of the scrollable container even though it's content is still wide.

    Because it is a block level element (display:block by default) and it's width is auto means it will take the width of it's parent.

    Now If we put a sticky element int there, Guess what will happen.

    [scrollable] {
      width: 300px;
      padding: 10px;
      background: red;
      border: 5px solid;
      overflow: auto;
    }
    
    [container] {
      padding: 10px;
      white-space: nowrap;
      background: orange;
    }
    
    [stuck] {
      background: pink;
      position: sticky;
      left: 0;
    }
    <div scrollable>
      <div container>
        <span stuck>stuck</span> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
      </div>
    </div>


    Here's an illustrating of the issue in your code, just by adding a background we can see the problem

    :root {
      --column-width: 70px;
    }
    
    .wrapper {
      font-family: sans-serif;
      max-width: 700px;
      height: 300px;
      overflow: auto;
    }
    
    .table-container {
      width: auto;
    }
    
    .table {
      position: relative;
      display: grid;
      grid-template-columns: 200px repeat(14, var(--column-width));
      background:orange;
    }
    
    .table.header {
      position: sticky;
      top: 0;
      z-index: 999;
    }
    
    .table.header+.table.header {
      position: sticky;
      top: 36px;
      ;
    }
    
    .table.header .row {
      background: #ccc !important;
    }
    
    .table .row.sticky {
      position: sticky;
      background: #eee;
    }
    
    .table .row.sticky:nth-child(1) {
      left: 0px;
    }
    
    .table .row.sticky:nth-child(2) {
      left: 200px;
    }
    
    .table .row.sticky:nth-child(3) {
      left: 270px;
    }
    
    input {
      width: 45px;
    }
    <div class="wrapper">
    
      <div class="table-container" role="table" aria-label="Destinations">
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Produkt</div>
          <div class="row sticky" role="columnheader">föreg. År</div>
          <div class="row sticky" role="columnheader">Totalt produkt</div>
          <div class="row" role="columnheader">v.1</div>
          <div class="row" role="columnheader">v.2</div>
          <div class="row" role="columnheader">v.3</div>
          <div class="row" role="columnheader">v.4</div>
          <div class="row" role="columnheader">v.5</div>
          <div class="row" role="columnheader">v.6</div>
          <div class="row" role="columnheader">v.7</div>
          <div class="row" role="columnheader">v.8</div>
          <div class="row" role="columnheader">v.9</div>
          <div class="row" role="columnheader">v.10</div>
          <div class="row" role="columnheader">v.11</div>
          <div class="row" role="columnheader">v.12</div>
        </div>
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Totalt vecla</div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
        </div>
        <div class="table row" role="rowgroup">
          <div class="row sticky" role="columnheader">Produktnamn</div>
          <div class="row sticky" role="columnheader">100 000 SEK</div>
          <div class="row sticky" role="columnheader">50 000 SEK</div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
        </div>
    </div>


    Solution 1

    Set a width to our row matching the content.

    In your case you have a grid-template-columns: 200px repeat(14, var(--column-width));

    From that we can deduce the width of our content 200px + (14 * var(--column-width))

    :root {
      --column-width: 70px;
    }
    
    .wrapper {
      font-family: sans-serif;
      max-width: 700px;
      height: 300px;
      overflow: auto;
    }
    
    .table-container {
      width: auto;
    }
    
    .table {
      position: relative;
      display: grid;
      grid-template-columns: 200px repeat(14, var(--column-width));
      width:calc(200px + (14 * var(--column-width)));
    }
    
    .table.header {
      position: sticky;
      top: 0;
      z-index: 999;
    }
    
    .table.header+.table.header {
      position: sticky;
      top: 36px;
      ;
    }
    
    .table.header .row {
      background: #ccc !important;
    }
    
    .table .row.sticky {
      position: sticky;
      background: #eee;
    }
    
    .table .row.sticky:nth-child(1) {
      left: 0px;
    }
    
    .table .row.sticky:nth-child(2) {
      left: 200px;
    }
    
    .table .row.sticky:nth-child(3) {
      left: 270px;
    }
    
    input {
      width: 45px;
    }
    <div class="wrapper">
    
      <div class="table-container" role="table" aria-label="Destinations">
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Produkt</div>
          <div class="row sticky" role="columnheader">föreg. År</div>
          <div class="row sticky" role="columnheader">Totalt produkt</div>
          <div class="row" role="columnheader">v.1</div>
          <div class="row" role="columnheader">v.2</div>
          <div class="row" role="columnheader">v.3</div>
          <div class="row" role="columnheader">v.4</div>
          <div class="row" role="columnheader">v.5</div>
          <div class="row" role="columnheader">v.6</div>
          <div class="row" role="columnheader">v.7</div>
          <div class="row" role="columnheader">v.8</div>
          <div class="row" role="columnheader">v.9</div>
          <div class="row" role="columnheader">v.10</div>
          <div class="row" role="columnheader">v.11</div>
          <div class="row" role="columnheader">v.12</div>
        </div>
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Totalt vecla</div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
        </div>
        <div class="table row" role="rowgroup">
          <div class="row sticky" role="columnheader">Produktnamn</div>
          <div class="row sticky" role="columnheader">100 000 SEK</div>
          <div class="row sticky" role="columnheader">50 000 SEK</div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
        </div>
    </div>

    I wouldn't recommend this, As we need to know the width of the content, And it's not as flexible.


    Solution 2

    Set a width to our row matching the content using min-content.

    :root {
      --column-width: 70px;
    }
    
    .wrapper {
      font-family: sans-serif;
      max-width: 700px;
      height: 300px;
      overflow: auto;
    }
    
    .table-container {
      width: auto;
    }
    
    .table {
      position: relative;
      display: grid;
      grid-template-columns: 200px repeat(14, var(--column-width));
      width:min-content;
    }
    
    .table.header {
      position: sticky;
      top: 0;
      z-index: 999;
    }
    
    .table.header+.table.header {
      position: sticky;
      top: 36px;
      ;
    }
    
    .table.header .row {
      background: #ccc !important;
    }
    
    .table .row.sticky {
      position: sticky;
      background: #eee;
    }
    
    .table .row.sticky:nth-child(1) {
      left: 0px;
    }
    
    .table .row.sticky:nth-child(2) {
      left: 200px;
    }
    
    .table .row.sticky:nth-child(3) {
      left: 270px;
    }
    
    input {
      width: 45px;
    }
    <div class="wrapper">
    
      <div class="table-container" role="table" aria-label="Destinations">
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Produkt</div>
          <div class="row sticky" role="columnheader">föreg. År</div>
          <div class="row sticky" role="columnheader">Totalt produkt</div>
          <div class="row" role="columnheader">v.1</div>
          <div class="row" role="columnheader">v.2</div>
          <div class="row" role="columnheader">v.3</div>
          <div class="row" role="columnheader">v.4</div>
          <div class="row" role="columnheader">v.5</div>
          <div class="row" role="columnheader">v.6</div>
          <div class="row" role="columnheader">v.7</div>
          <div class="row" role="columnheader">v.8</div>
          <div class="row" role="columnheader">v.9</div>
          <div class="row" role="columnheader">v.10</div>
          <div class="row" role="columnheader">v.11</div>
          <div class="row" role="columnheader">v.12</div>
        </div>
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Totalt vecla</div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
        </div>
        <div class="table row" role="rowgroup">
          <div class="row sticky" role="columnheader">Produktnamn</div>
          <div class="row sticky" role="columnheader">100 000 SEK</div>
          <div class="row sticky" role="columnheader">50 000 SEK</div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
        </div>
    </div>

    I wouldn't recommend this solution yet, Barbecue it's not widely supported yet.


    Solution 3

    Make our grid inline.

    inline level elements will grow and shrink to fit their content.

    The most viable solution of the three.

    :root {
      --column-width: 70px;
    }
    
    .wrapper {
      font-family: sans-serif;
      max-width: 700px;
      height: 300px;
      overflow: auto;
    }
    
    .table-container {
      width: auto;
    }
    
    .table {
      position: relative;
      /* display: grid;  Removed */
      display: inline-grid;  /* NEW */
      grid-template-columns: 200px repeat(14, var(--column-width));
    }
    
    .table.header {
      position: sticky;
      top: 0;
      z-index: 999;
    }
    
    .table.header+.table.header {
      position: sticky;
      top: 36px;
      ;
    }
    
    .table.header .row {
      background: #ccc !important;
    }
    
    .table .row.sticky {
      position: sticky;
      background: #eee;
    }
    
    .table .row.sticky:nth-child(1) {
      left: 0px;
    }
    
    .table .row.sticky:nth-child(2) {
      left: 200px;
    }
    
    .table .row.sticky:nth-child(3) {
      left: 270px;
    }
    
    input {
      width: 45px;
    }
    <div class="wrapper">
    
      <div class="table-container" role="table" aria-label="Destinations">
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Produkt</div>
          <div class="row sticky" role="columnheader">föreg. År</div>
          <div class="row sticky" role="columnheader">Totalt produkt</div>
          <div class="row" role="columnheader">v.1</div>
          <div class="row" role="columnheader">v.2</div>
          <div class="row" role="columnheader">v.3</div>
          <div class="row" role="columnheader">v.4</div>
          <div class="row" role="columnheader">v.5</div>
          <div class="row" role="columnheader">v.6</div>
          <div class="row" role="columnheader">v.7</div>
          <div class="row" role="columnheader">v.8</div>
          <div class="row" role="columnheader">v.9</div>
          <div class="row" role="columnheader">v.10</div>
          <div class="row" role="columnheader">v.11</div>
          <div class="row" role="columnheader">v.12</div>
        </div>
        <div class="table header" role="rowgroup">
          <div class="row sticky" role="columnheader">Totalt vecla</div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row sticky" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader"></div>
          <div class="row" role="columnheader">100 000 SEK</div>
        </div>
        <div class="table row" role="rowgroup">
          <div class="row sticky" role="columnheader">Produktnamn</div>
          <div class="row sticky" role="columnheader">100 000 SEK</div>
          <div class="row sticky" role="columnheader">50 000 SEK</div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
          <div class="row" role="columnheader"><input type="number" /></div>
        </div>
    </div>


    Note: I had to lower the number of row to post the answer.