2

I am trying to rebuild an old site with grid layout. Everything went fine until I started to fill the page with content. See the code snippet and images. Short content Long content If the content of the article (3) is short, a gap appears between the article text and bottom (5). As the content of the article becomes longer, a gap appears between the sidebar (2) and sidebar1 (4). Only when the sidebar and article are equal in length, there are no gaps. I need that the sidebar1 (4) with sidebar2 (6) will be pulled up to the last menu item in the sidebar, and the bottom (5) along with base (7) will be pulled up to the article text independently of its length. Is it possible to do this with grid-only approach and without (or with minor) changes in html.

I played with numbering, naming, and rearranging the grid items, added some spacer blocks but so far got the same outcome. Could someone point me in the right direction?

#page-wrapper {
 display: grid;
 max-width: 1280px;
 margin: 0 auto;
 justify-items: stretch;
 align-items: start;
 grid-gap: 5px;
 background: #ccc;
 grid-template-areas: 
 "header header"
 "sidebar article"
 "sidebar1 bottom"
 "sidebar2 base"
 "footer footer";
 grid-template-columns: 320px 1fr; 
 grid-template-rows: auto;
}             
#page-wrapper > div, header, article, footer  {
 border: 1px solid #888;
 font-size: 1.2em;
 min-height: 50px;
 padding: 15px;
 color: #fff;
}
li {
 list-style: none;
}  
header {
 background: #557;
 grid-area: header;
}
.sidebar {
 background: #55a;
 grid-area: sidebar;
 /* align-self: stretch; */
}
article {
 grid-area: article;
 background: #755;
 /* align-self: stretch; */
}
.sidebar1 {
 grid-area: sidebar1;
 background: #351;
}
.bottom {
 grid-area: bottom;
 background: #632;
}
.sidebar2 {
 grid-area: sidebar2;
 background: #125;
}
.base{
 grid-area: base;
 background: #33b;
}
footer{
 grid-area: footer;
 background: #376;
}
<!doctype html>
<html>
<head>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1" />
 <link rel="stylesheet" href="style.css" />
</head>
<body>
 <div id="page-wrapper">
  <header>
   <h3>1 Header</h3>
  </header>
  <div class="sidebar">
   2 <ul>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   </ul>
  </div>
  <article>
   3 <p>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.</p>
  </article>
  <div class="sidebar1">4</div>
  <div class="bottom">5</div>
  <div class="sidebar2">6</div>
  <div class="base">7</div>
  <footer><h3>8 Footer</h3></footer>
 </div>
 </body>
</html>
Ken
  • 39
  • 1
  • 5
  • Humm, if I understand what you are asking, it means that depending on the content's length, you will have a gap below 7 or 6, right ? – Arkellys Jan 29 '19 at 11:06
  • Arkellys, no. I mean the gaps with red arrows i.e. above 4 and 5. – Ken Jan 29 '19 at 12:17
  • yes, but with the fix you are asking, the gap will be either below `sidebar2` or below `base`? – Arkellys Jan 29 '19 at 12:53
  • I don't believe this is possible with Grid Layout alone. Here's an explanation: https://stackoverflow.com/q/44377343/3597276 – Michael Benjamin Jan 29 '19 at 12:54
  • Michael_B, thanks for the link. Studying. – Ken Jan 29 '19 at 13:21
  • Arkellys, thanks for the elaborating question. I think, you've got the point. The gap can / should be below sidebar2 and above footer. – Ken Jan 29 '19 at 14:24

2 Answers2

1

I am not very familiar with grid so maybe there is a better way to do it, however, here is a way to solve your problem :

.grid {
  display: grid;
  justify-items: stretch;
  align-items: start;
  grid-gap: 5px;
}

#page-wrapper {
  max-width: 1280px;
  margin: 0 auto;
  background: #ccc;
  grid-template-areas:
   "header header"
   "side content"
   "footer footer";
  grid-template-columns: 320px 1fr;
  grid-template-rows: auto;
}

.side > div, .content > div, header, article, footer {
  border: 1px solid #888;
  font-size: 1.2em;
  min-height: 50px;
  padding: 15px;
  color: #fff;
}

li {
  list-style: none;
}

header {
  grid-area: header;
  background: #557;
}

.side {
  grid-area: side;
  background: yellow;
  grid-template-areas:
   "sidebar"
   "sidebar1"
   "sidebar2";
}

.sidebar {
  grid-area: sidebar;
  background: #55a;
}

.sidebar1 {
  grid-area: sidebar1;
  background: #351;
}

.sidebar2 {
  grid-area: sidebar2;
  background: #125;
}

.content {
  grid-area: content;
  background: red;
  grid-template-areas:
   "article"
   "bottom"
   "base";
}

article {
  grid-area: article;
  background: #755;
}

.bottom {
  grid-area: bottom;
  background: #632;
}

.base {
  grid-area: base;
  background: #33b;
}

footer {
  grid-area: footer;
  background: #376;
}
<body>
  <div id="page-wrapper" class="grid">
    <header>
      <h3>1 Header</h3>
    </header>
    
    <div class="side grid">
      <div class="sidebar">
        2 <ul>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
        </ul>
      </div>
      <div class="sidebar1">4</div>
      <div class="sidebar2">6</div>
    </div>
    
    <div class="content grid">
      <article>
        3 <p>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.</p>
      </article>

      <div class="bottom">5</div>
      <div class="base">7</div>
    </div>
  
    <footer><h3>8 Footer</h3></footer>
  </div>
</body>

This require to change the HTML a bit. With this approach, you need to wrap all the side elements (.sidebar, .sidebar1 and .sidebar2) in a div and do the same with the content elements (article, .bottom and .base).

grid-template-areas then become :

"header header"
"side content"
"footer footer"

This way, the gap due to the different content's lengths will be below the wrapping divs instead of between the elements.

Both wrapping div can have their own grid environment as the example above, but if you don't need to position the elements in a complex way, you can simplify the code:

#page-wrapper {
  display: grid;
  justify-items: stretch;
  align-items: start;
  grid-gap: 5px;
  max-width: 1280px;
  margin: 0 auto;
  background: #ccc;
  grid-template-areas:
   "header header"
   "side content"
   "footer footer";
  grid-template-columns: 320px 1fr;
  grid-template-rows: auto;
}

.side > div, .content > div, header, article, footer {
  border: 1px solid #888;
  font-size: 1.2em;
  min-height: 50px;
  padding: 15px;
  color: #fff;
}

li {
  list-style: none;
}

header {
  grid-area: header;
  background: #557;
}

.side > div:not(:last-child), article, .content > div:not(:last-child) {
  margin-bottom: 5px;
}

.side {
  grid-area: side;
  background: yellow;
}

.sidebar { background: #55a; }
.sidebar1 { background: #351; }
.sidebar2 { background: #125; }

.content {
  grid-area: content;
  background: red;
}

article { background: #755; }
.bottom { background: #632; }
.base { background: #33b; }

footer {
  grid-area: footer;
  background: #376;
}
<body>
  <div id="page-wrapper">
    <header>
      <h3>1 Header</h3>
    </header>
    
    <div class="side">
      <div class="sidebar">
        2 <ul>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
          <li>Menu item </li>
        </ul>
      </div>
      <div class="sidebar1">4</div>
      <div class="sidebar2">6</div>
    </div>
    
    <div class="content">
      <article>
        3 <p>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.</p>
      </article>

      <div class="bottom">5</div>
      <div class="base">7</div>
    </div>
  
    <footer><h3>8 Footer</h3></footer>
  </div>
</body>
Arkellys
  • 5,562
  • 2
  • 16
  • 40
  • This will work, thanks. Although some restrictions in adaptability stiil remain, that's why I'd rather wrap only the 3 sidebar elements, leaving the main section unwrapped. It doesn't solve the problem completely too but gives a bit more flexibility. Regarding your code, there would be enough to state "side content" just once. – Ken Jan 30 '19 at 08:23
  • Ah yes I see. Sorry that I can't help you more, I am way more used to do full flexbox layouts. =) And yes thanks! I will edit the code. – Arkellys Jan 30 '19 at 08:33
0

I found a pretty simple solution. Now CSS supplemented by empty grid-template-area "sidebar push", (no selector needed). Code snippet below.

#page-wrapper {
    min-height:100vh;
    display: grid;
    max-width: 1280px;
    margin: 0 auto;
    justify-items: stretch;
    align-items: start;
    grid-gap: 5px;
    background: #ccc;
    grid-template-areas: 
    "header header"
    "sidebar article"
    "sidebar bottom"
    "sidebar base"
    "sidebar push"
    /* try to remove the "sidebar push" and see what will happen  */
    "footer footer";
    grid-template-columns: 1fr 3fr; 
    grid-template-rows: auto;
} 
           
#page-wrapper > div, header, article, footer  {
    border: 1px solid #888;
    font-size: 1.2em;
    min-height: 50px;
    padding: 7px;
    color: #fff;
}

li {
    list-style: none;
}

header {
    background: #557;
    grid-area: header;
}

.sidebar {
    background: #55a;
    grid-area: sidebar;
}

article {
    grid-area: article;
    background: #755;
}

.sidebar1 {
    background: #351;
}

.sidebar2 {
    background: #125;
}

.bottom {
    grid-area: bottom;
    background: #632;
}

.base {
    grid-area: base;
    background: #33b;
}

footer{
    grid-area: footer;
    background: #376;
}
<!doctype html>
<html>
<head>
 <meta charset="utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1" />
 <link rel="stylesheet" href="style.css" />
</head>
<body>
 <div id="page-wrapper">
  <header>
   <h3>header</h3>
  </header>
  <article>
   article <p>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.</p>
  </article>
  <div class="sidebar">
   sidebar 
  <ul>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
   <li>Menu item </li>
  </ul>
  <div class="sidebar1">sidebar1</div>
  <div class="sidebar2">sidebar1</div>
  </div>
  <div class="bottom">bottom</div>
  <div class="base">base</div>
  <footer><h3>footer</h3></footer>
 </div>
 </body>
</html>
m02ph3u5
  • 3,022
  • 7
  • 38
  • 51
Ken
  • 39
  • 1
  • 5