skip to Main Content

I have markup with the following structure. I would like to have a responsive layout with three break points that works as follows:

  • Large viewport, three columns:
    ".......  nav      ........"
    "toc-pkg  preamble toc-page"
    "toc-pkg  content  toc-page"
    
  • Medium viewport, two columns, with in the toc grid area both toc-page and toc-pkg
    following one after the other:

    " nav      ..." 
    " preamble toc"
    " content  toc"
    
  • Narrow viewport one columns:
    " nav      "
    " preamble " 
    " toc-page " 
    " content  " 
    " toc-pkg  " 
    

While it’s easy to get the first and third layout. I can’t get the second one. If I try to assign both toc-page and toc-pkg to the toc grid area they overlap (as expected it seems), but I’d like them to stack.

Is there any solution that involves a single markup structure and only CSS?

.grid>* {
  display: flex;
  justify-content: center;
  align-items: center;
}

.nav {
  height: 1em;
  background: #3C354F;
  color: white;
  grid-area: nav;
}

.toc-page {
  height: 4em;
  width: 100%;
  background: #E0695E;
  grid-area: toc-page;
}

.toc-pkg {
  height: 2em;
  width: 100%;
  background: #E0695E;
  grid-area: toc-pkg;
}

.content {
  height: 10em;
  background: #DFD4C7;
  grid-area: content;
}

.preamble {
  height: 6em;
  background: #F3F3E3;
  grid-area: preamble;
}

.tocs {
  display: flex;
  grid-area: tocs;
  flex-direction: column;
  justify-content: start;
  align-items: center
}

.grid {
  display: grid;
  gap: 1rem;
}

.grid {
  grid-template-rows: auto;
  grid-template-areas: ". nav ." "toc-page preamble toc-pkg" "toc-page content toc-pkg";
}

@media (max-width: 40em) {
  .toc-page {
    grid-area: toc;
  }
  .toc-pkg {
    grid-area: toc;
  }
  .grid {
    grid-template-rows: auto;
    grid-template-areas: "nav ." "preamble toc" "content toc";
  }
}

@media (max-width: 30em) {
  .toc-page {
    grid-area: toc-page;
  }
  .toc-pkg {
    grid-area: toc-pkg;
  }
  .grid {
    grid-template-rows: auto;
    grid-template-areas: "nav" "preamble" "toc-page" "content" "toc-pkg";
  }
}

body {
  margin: 1rem;
}
<div class="grid medium">
  <div class="nav">NAV</div>
  <div class="preamble">PRE</div>
  <div class="toc-page">TOC-PAGE</div>
  <div class="toc-pkg">TOC-PKG</div>
  <div class="content">TXT</div>
</div>

2

Answers


  1. Chosen as BEST ANSWER

    @Paulie_D suggested using display: contents (thanks!). By tweaking the markup to

    <div class="grid medium">
      <div class="nav">NAV</div>
      <div class="preamble">PRE</div>
      <div class="tocs"
        <div class="toc-page">TOC-PAGE</div>
        <div class="toc-pkg">TOC-PKG</div>
      </div>
      <div class="content">TXT</div>
    </div>
    

    Allows this to be made to work as:

    .grid > * {  display: flex; justify-content: center; 
             align-items: center;  }
    .nav { height: 1em; background: #3C354F; color: white; grid-area: nav; }
    .toc-page { height: 4em; width: 100%; background: #E0695E; 
            grid-area: toc-page; }
    .toc-pkg  { height: 2em; width: 100%; background: #E0695E; 
            grid-area: toc-pkg; }
    .content { height: 10em; background: #DFD4C7; grid-area: content; }
    .preamble { height: 5em; background: #F3F3E3; grid-area: preamble; }
    .grid { grid-template-rows: auto; display: grid; gap: 1rem;}
    .tocs { display: contents; grid-area: unset; }
    .grid {
       grid-template-areas: 
     ". nav ."
     "toc-page preamble toc-pkg"
     "toc-page content toc-pkg";
     }
    
    @media (max-width: 80em) {
      .toc-page { grid-area: unset; }
      .toc-pkg { grid-area: unset; }
      .tocs { display: block; grid-area: toc }
      .grid {
      grid-template-areas: 
    "nav ."
    "preamble toc"
    "content toc";
    }
    }
    
    @media (max-width: 60em) {
      .toc-page { grid-area: toc-page; }
      .toc-pkg { grid-area: toc-pkg; }
      .tocs { display: contents; grid-area: unset }
      .grid {
     grid-template-areas: 
      "nav"
      "preamble" 
      "toc-page"
      "content"
      "toc-pkg";
      }
    }
    body { margin: 1rem; }
     <div class="grid medium">
      <div class="nav">NAV</div>
      <div class="preamble">PRE</div>
      <div class="tocs">
    <div class="toc-page">TOC-PAGE</div>
    <div class="toc-pkg">TOC-PKG</div>
      </div>
      <div class="content">TXT</div>
    </div>


  2. At the required break-point switch the flow to column and adjust the areas to extend the preamble across two rows.

      .preamble {
        grid-row: span 2;
      }
    
      .grid {
        grid-template-rows: auto;
        grid-template-areas: 
          "nav ." 
          "preamble toc-page" 
          "preamble toc-pkg" 
          "content .";
      }
    

    I swapped out the height of the .preamble for a min-height: 6em; but this is just a matter of preference.

    .grid>* {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .nav {
      height: 1em;
      background: #3c354f;
      color: white;
      grid-area: nav;
    }
    
    .toc-page {
      height: 4em;
      width: 100%;
      background: #e0695e;
      grid-area: toc-page;
    }
    
    .toc-pkg {
      height: 2em;
      width: 100%;
      background: #e0695e;
      grid-area: toc-pkg;
    }
    
    .content {
      height: 10em;
      background: #dfd4c7;
      grid-area: content;
    }
    
    .preamble {
      min-height: 6em;
      background: #f3f3e3;
      grid-area: preamble;
    }
    
    .tocs {
      display: flex;
      grid-area: tocs;
      flex-direction: column;
      justify-content: start;
      align-items: center;
    }
    
    .grid {
      display: grid;
      gap: .25rem;
    }
    
    .grid {
      grid-template-rows: auto;
      grid-template-areas: ". nav ." "toc-page preamble toc-pkg" "toc-page content toc-pkg";
    }
    
    @media (max-width: 40em) {
      .grid {
        grid-auto-flow: column;
      }
      .preamble {
        grid-row: span 2;
      }
      .toc-page {
        grid-area: toc-page;
      }
      .toc-pkg {
        grid-area: toc-pkg;
      }
      .grid {
        grid-template-rows: auto;
        grid-template-areas: "nav ." "preamble toc-page" "preamble toc-pkg" "content .";
      }
    }
    
    @media (max-width: 30em) {
      .toc-page {
        grid-area: toc-page;
      }
      .toc-pkg {
        grid-area: toc-pkg;
      }
      .grid {
        grid-template-rows: auto;
        grid-template-areas: "nav" "preamble" "toc-page" "content" "toc-pkg";
      }
    }
    
    body {
      margin: 1rem;
    }
    <div class="grid medium">
      <div class="nav">NAV</div>
      <div class="preamble">PRE</div>
      <div class="toc-page">TOC-PAGE</div>
      <div class="toc-pkg">TOC-PKG</div>
      <div class="content">TXT</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search