Search code examples
csscss-grid

Responsive Table with grid-template-areas


I have this table working the way I want using grid-template-areas, collapsing columns on smaller screens, but I'm wondering if there's a better way to do the css than what I currently have?

Feels like there has to be a better solution that I'm missing other than adding a new class for every new row in the table.

Code pen example has it working the way I want, using 2 columns on screens smaller than 800px: https://codepen.io/BigProof/pen/gOEzeJv

Large screen:

H1 H2 H3 H4
T1 T2 T3 T4
T11 T22 T33 T44

Smaller screen:

H1 H2
T1 T2
T11 T22
H3 H4
T3 T4
T33 T44

Here's the code:

body {
  background-color: #15202b
}

.grid {
  color: #eee;
  display: grid;
  grid-template-areas: "Heading1 Heading2 Heading3 Heading4" "Text1 Text2 Text3 Text4" "Text11 Text22 Text33 Text44" "Text111 Text222 Text333 Text444";
  grid-gap: 6px;
  background-color: #224263;
  padding: 6px;
}

.grid>div {
  background-color: #15202b;
  text-align: center;
  padding: 20px 0;
  font-size: 30px;
}

@media (max-width: 800px) {
  .grid {
    grid-template-areas: "Heading1 Heading2" "Text1 Text2" "Text11 Text22" "Text111 Text222" "Heading3 Heading4" "Text3 Text4" "Text33 Text44" "Text333 Text444";
  }
}

.Heading1,
.Heading2,
.Heading3,
.Heading4 {
  font-weight: 900;
  text-transform: uppercase;
}

.Heading1 {
  grid-area: Heading1;
}

.Heading2 {
  grid-area: Heading2;
}

.Heading3 {
  grid-area: Heading3;
}

.Heading4 {
  grid-area: Heading4;
}

.Text1 {
  grid-area: Text1;
}

.Text11 {
  grid-area: Text11;
}

.Text111 {
  grid-area: Text111;
}

.Text2 {
  grid-area: Text2;
}

.Text22 {
  grid-area: Text22;
}

.Text222 {
  grid-area: Text222;
}

.Text3 {
  grid-area: Text3;
}

.Text33 {
  grid-area: Text33;
}

.Text333 {
  grid-area: Text333;
}

.Text4 {
  grid-area: Text4;
}

.Text44 {
  grid-area: Text44;
}

.Text444 {
  grid-area: Text444;
}
<div class="grid">
  <div class="Heading1">Heading1</div>
  <div class="Heading2">Heading2</div>
  <div class="Heading3">Heading3</div>
  <div class="Heading4">Heading4</div>
  <div class="Text1">Text1</div>
  <div class="Text11">Text11</div>
  <div class="Text111">Text111</div>
  <div class="Text2">Text2</div>
  <div class="Text22">Text22</div>
  <div class="Text222">Text222</div>
  <div class="Text3">Text3</div>
  <div class="Text33">Text33</div>
  <div class="Text333">Text333</div>
  <div class="Text4">Text4</div>
  <div class="Text44">Text44</div>
  <div class="Text444">Text444</div>
</div>


Solution

  • One method woruld be to alter the HTML so it flowed in rows (for the wider case) naturally and then in the two column case explictly put items into their correct rows where necessary.

    <style>
      body {
        background-color: #15202b
      }
      
      .grid {
        color: #eee;
        display: grid;
        grid-gap: 6px;
        background-color: #224263;
        padding: 6px;
        grid-template-columns: 1fr 1fr 1fr 1fr;
        width: 100vw;
      }
      
      .grid>div {
        background-color: #15202b;
        text-align: center;
        padding: 20px 0;
        font-size: 30px;
      }
      
      .Heading {
        font-weight: 900;
        text-transform: uppercase;
      }
      
      @media (max-width: 800px) {
        .grid {
          grid-template-columns: 1fr 1fr;
        }
        .grid :nth-child(3),
        .grid :nth-child(4) {
          grid-row: 5;
        }
        .grid :nth-child(7),
        .grid :nth-child(8) {
          grid-row: 6;
        }
        .grid :nth-child(11),
        .grid :nth-child(12) {
          grid-row: 7;
        }
      }
    </style>
    <div class="grid">
      <div class="Heading">Heading1</div>
      <div class="Heading">Heading2</div>
      <div class="Heading">Heading3</div>
      <div class="Heading">Heading4</div>
      <div>Text1</div>
      <div>Text2</div>
      <div>Text3</div>
      <div>Text4</div>
      <div>Text11</div>
      <div>Text22</div>
      <div>Text33</div>
      <div>Text44</div>
      <div>Text111</div>
      <div>Text222</div>
      <div>Text333</div>
      <div>Text444</div>
    </div>