Search code examples
csscss-grid

Grid Template Layout - aligning multiple items in same column (self align start)


I'm trying to use grid template to build a layout for different views (mobile / desktop etc).

I'm using grid-template-area.

For mobile it is easy since I'm using just 1 column but when I go to desktop I want to build 2 columns. For desktop first column should show as in the image, but for the second column I'd like to align everything on top, next to each other.

Is there a way to move description just after title without any space or it is not possible with grid? Please note that the height of any box should remain dynamic.

Current Behavior enter image description here

Expected Behavior enter image description here

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.title {
  grid-area: title;
  min-height: 30px;
  background-color: green;
}

.description {
  grid-area: description;
  background-color: lightgreen;
  min-height: 300px;
}

.price {
  grid-area: price;
  background-color: teal;
  min-height: 30px;
}

.config {
  grid-area: config;
  background-color: purple;
  min-height: 150px;
}

.add {
  grid-area: add;
  background-color: red;
  min-height: 50px;
}

.carousel {
  grid-area: carousel;
  background-color: orange;
  min-height: 500px;
}

.features {
  grid-area: features;
  background-color: pink;
  min-height: 400px;
}

.specifications {
  grid-area: specifications;
  background-color: gray;
  min-height: 300px;
}

.related {
  grid-area: related;
  background-color: aqua;
  min-height: 400px;
}

.wrapper {
  display: grid;
  grid-template-areas: "title" 
                       "description"
                       "price"
                       "config"
                       "add"
                       "carousel"
                       "features"
                       "specifications"
                       "related";
  grid-template-rows: auto;
}
@media screen and (min-width: 600px) {
  .wrapper {
    grid-template-columns: 3fr 1fr;
    grid-template-areas: "carousel title"
                         "features description" 
                         "specifications price" 
                         "related config" 
                         ". add";
  }
}
.wrapper > div {
  display: flex;
  color: white;
  justify-content: center;
  align-items: center;
  font-size: 42px;
  padding: 12px;
  align-self: start;
}/*# sourceMappingURL=styles.css.map */
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div class="wrapper">
      <div class="title">TITLE</div>
      <div class="description">DESCRIPTION</div>
      <div class="price">PRICE</div>
      <div class="config">CONFIG</div>
      <div class="add">ADD TO BASKET</div>
      <div class="carousel">CAROUSEL</div>
      <div class="features">KEY FEATURES</div>
      <div class="specifications">SPECIFICATIONS</div>
      <div class="related">RELATED PRODUCTS</div>
    </div>
  </body>
</html>


Solution

  • If you want to change the order of the blocks in the mobile version, for example put .carousel after .title, I offer you a slightly improved version @SyndRain.
    Namely, apply display: contents; to .sidebar in the mobile version - this will allow you to move the blocks as you like using grid-template-areas:

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    .title {
      grid-area: title;
      min-height: 30px;
      background-color: green;
    }
    
    .description {
      grid-area: description;
      background-color: lightgreen;
      min-height: 300px;
    }
    
    .price {
      grid-area: price;
      background-color: teal;
      min-height: 30px;
    }
    
    .config {
      grid-area: config;
      background-color: purple;
      min-height: 150px;
    }
    
    .add {
      grid-area: add;
      background-color: red;
      min-height: 50px;
    }
    
    .carousel {
      grid-area: carousel;
      background-color: orange;
      min-height: 500px;
    }
    
    .features {
      grid-area: features;
      background-color: pink;
      min-height: 400px;
    }
    
    .specifications {
      grid-area: specifications;
      background-color: gray;
      min-height: 300px;
    }
    
    .related {
      grid-area: related;
      background-color: aqua;
      min-height: 400px;
    }
    
    .wrapper {
      display: grid;
      grid-template-areas: "title" 
                           "carousel"
                           "description"
                           "price"
                           "config"
                           "add"
                           "features"
                           "specifications"
                           "related";
      grid-template-rows: auto;
      @media screen and (min-width: 600px) {
        grid-template-columns: 3fr 1fr;
        grid-template-areas: "carousel sidebar"
                             "features sidebar"
                             "specifications sidebar"
                             "related sidebar"
                             "add sidebar";
      }
    }
    
    .sidebar {
      display: contents;
      @media screen and (min-width: 600px) {
          display: block;
          grid-area: sidebar;
      }
    }
    
    .wrapper div:not(.sidebar) {
      display: flex;
      color: white;
      justify-content: center;
      align-items: center;
      padding: 12px;
      align-self: start;
      font-size: 32px;
      @media screen and (min-width: 600px) {
        font-size: 42px;
      }
    }
    <div class="wrapper">
      <div class="carousel">CAROUSEL</div>
      <div class="features">KEY FEATURES</div>
      <div class="specifications">SPECIFICATIONS</div>
      <div class="related">RELATED PRODUCTS</div>
      <div class="sidebar">
        <div class="title">TITLE</div>
        <div class="description">DESCRIPTION</div>
        <div class="price">PRICE</div>
        <div class="config">CONFIG</div>
        <div class="add">ADD TO BASKET</div>
      </div>
    </div>