skip to Main Content

I’m experimenting with Grid layouts but I’m having difficulty placing a series of child elements at the top of the grid and the last child element at the bottom.

  • align-self: end used on the last child element positions it at the bottom but it leaves boxes 2 and 3 in the middle.
  • align-content: start used on the parent container positions the top elements correctly except it also positions the last item at the top which won’t work.

Getting this done with Flexbox is simple enough.

  1. flex-direction: column on the parent.
  2. justify-content: space-between on the parent.
  3. Add a wrapper container around the top content.

This causes the wrapper to be positioned at the top and the bottom element to be positioned at the bottom.

Is there a simple pattern that accomplishes the same thing with Grid? If possible I’d like to do this without adding a wrapper element.

.container {
  display: grid;
  height: 100vh;
  background-color: grey;
}

.top_one {
  height: 50px;
  background-color: red;
}

.top_two {
  height: 50px;
  background-color: green;
}

.top_three {
  height: 50px;
  background-color: purple;
}

.bottom_copyright {
  align-self: end;
  height: 50px;
  background-color: blue;
}
<div class="container">
  <div class="top_one">box 1</div>
  <div class="top_two">box 2</div>
  <div class="top_three">box 3</div>
  <div class="bottom_copyright">copyright</div>
</div>

2

Answers


  1. You can manually add a blank row between them:

    .container {
      grid-template-rows: repeat(3, auto) 1fr auto;
    }
    
    .bottom_copyright {
      grid-row: -1;
    }
    

    Try it:

    .container {
      --children-count: 4;
      grid-template-rows: repeat(calc(var(--children-count) - 1), auto) 1fr auto;
    }
    
    .bottom_copyright {
      grid-row: -1;
    }
    
    
    /* Original styles */
    
    .container {
      display: grid;
      height: 100vh;
      background-color: grey;
    }
    
    .top_one {
      height: 50px;
      background-color: red;
    }
    
    .top_two {
      height: 50px;
      background-color: green;
    }
    
    .top_three {
      height: 50px;
      background-color: purple;
    }
    
    .bottom_copyright {
      height: 50px;
      background-color: blue;
    }
    
    /* Demo only */
    
    body {
      margin: 0;
    }
    <div class="container">
      <div class="top_one">box 1</div>
      <div class="top_two">box 2</div>
      <div class="top_three">box 3</div>
      <div class="bottom_copyright">copyright</div>
    </div>
    Login or Signup to reply.
  2. You could do it by explicitly setting the grid rows and using either margin-top: auto or align-self: end on the last item:

    .container {
      display: grid;
      grid-template-rows: 50px 50px 50px 1fr;
      height: 100vh;
      background-color: grey;
    }
    
    .top_one {
      height: 50px;
      background-color: red;
    }
    
    .top_two {
      height: 50px;
      background-color: green;
    }
    
    .top_three {
      height: 50px;
      background-color: purple;
    }
    
    .bottom_copyright {
      height: 50px;
      background-color: blue;
      margin-top: auto;
      /* align-self: end; */
    }
    <div class="container">
      <div class="top_one">box 1</div>
      <div class="top_two">box 2</div>
      <div class="top_three">box 3</div>
      <div class="bottom_copyright">copyright</div>
    </div>

    As an aside, you don’t need the extra wrapper when doing this with Flexbox. In fact, it’s quite a bit simpler with Flexbox, again using margin: auto on the last item:

    .container {
      display: flex;
      flex-direction: column;
      height: 100vh;
      background-color: grey;
    }
    
    .top_one {
      height: 50px;
      background-color: red;
    }
    
    .top_two {
      height: 50px;
      background-color: green;
    }
    
    .top_three {
      height: 50px;
      background-color: purple;
    }
    
    .bottom_copyright {
      height: 50px;
      background-color: blue;
      margin-top: auto;
    }
    <div class="container">
      <div class="top_one">box 1</div>
      <div class="top_two">box 2</div>
      <div class="top_three">box 3</div>
      <div class="bottom_copyright">copyright</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search