Advanced table/grid with variable number of columns & widths & overflows

Viewed 58

I'm in need of some help. I'm trying to create an advanced grid/table.

I have rows with:

  • a header
  • subheaders
  • rows that may contain info

my first column:

  • header: empty
  • subheader: name of squad
  • inforow: name of squadmember

what I need is a sort of grid/table with these requirements:

  • header: sticky
  • subheader: sticky under the header (until the next subheader arrives)
  • first column: fixed width of 250px
  • number of columns: variable
  • number of rows: variable
  • height of columns: 40px
  • a column with 0 infocells: fixed width of 50px
    • except when all columns are empty: all columns same width
  • a column where at least one item has info: minimum width of 100px
    • but when there is more space available: fill the remaining space evenly
  • infocolumns need to have a horizontal scroll when my space is overflown, for example:
    • available width for grid: 1000px
    • available width for infocolumns: 1000px - 250px = 750px
    • i have 10 infocolumns: 8 with info, 2 empty
    • so: 8 * at least 100px (scalable) & 2 * 50px → 900px
      • the infocolumns need to have a horizontal scroll, the first column, with squad(member)names, is sticky

I don't know exactly where the infocells will be before the data is fetched, but I already need to show a grid/table. Looping over the data in the parentcomponent would be less efficient, so hopefully it can be solved by html/css.
I do know how many columns there will be.

Maybe table isn't the right approach here either.

I'm almost there, but on a big screen the fixed width of the first column is variable and the horizontal flow isn't there yet.
This is what I got so far:

* {
   box-sizing: border-box;
}

table {
  width: 100%;
}

thead {
  position: sticky;
  top: 0;
  height: 40px;
  background: lightsalmon;
  z-index: 1;
}

thead:not(:first-of-type) {
  top: 44px;
}

th:first-of-type {
  width: 250px;
  min-width: 250px;
  max-width: 250px;
}

td:first-of-type {
  width: 250px;
  min-width: 250px;
  max-width: 250px;
}

td {
  height: 40px;
  background: lightpink;
}

td.has_data {
  min-width: 100px;
  width: auto;
}

td:not(.has_data) {
  min-width: 50px;
  width: 50px;
  max-width: 50px;
}
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" type="text/css" href="styles.css" />
  </head>
  <body>
    <div class="table_wrapper">
      <table>
        <thead>
          <th></th>
          <th>01/03</th>
          <th>02/03</th>
          <th>03/03</th>
          <th>04/03</th>
          <th>05/03</th>
          <th>06/03</th>
          <th>07/03</th>
          <th>08/03</th>
        </thead>
        <thead>
          <th>the programmers</th>
          <th>01:00</th>
          <th>02:00</th>
          <th>03:00</th>
          <th>04:00</th>
          <th>05:00</th>
          <th>06:00</th>
          <th>07:00</th>
          <th>08:00</th>
        </thead>
        <tbody>
          <tr>
            <td>Jeff</td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
      </tr>
      <tr>
        <td>Eric</td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td class="has_data">info!</td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td>Sarah</td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td class="has_data">more info!</td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
    </tbody>
    <thead>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
      <th>9</th>
    </thead>
    <tbody>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>

      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
      <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
    </tbody>
  </table>
</div>
  </body>
</html>

1 Answers
Related