Home > other >  Vertically center grid items in a column
Vertically center grid items in a column

Time:04-22

I have a grid that's two columns side by side. However, there's an odd number of elements, so I would like to offset the right column so it's centered vertically against the left column.

What would be the best way to do that using grid?

Here's an example how i want the layout to look:

enter image description here

Here's an example: https://codepen.io/patricktm/pen/JjMzQWj

body {
  max-width: 1000px;
  margin: auto;
}

.grid-item {
  background-color: #ccc;
  border: 1px solid;
  height: 200px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1em;
}
<body>
  <div class='grid'>
    <div class='grid-item'>1</div>
    <div class='grid-item'>2</div>
    <div class='grid-item'>3</div>
    <div class='grid-item'>4</div>
    <div class='grid-item'>5</div>
    <div class='grid-item'>6</div>
    <div class='grid-item'>7</div>
  </div>
</body>

CodePudding user response:

This layout isn't really feasible with Grid because there are fix row tracks that prevent the free flow of items across the column.

You're basically asking the top item in the second column to somehow space itself down in the first row track and cross into the second track, pushing down the other items along the way.

Grid doesn't work this way. The matter is discussed in detail in this post:

One simple way to make this layout work uses flexbox, which has no column or row tracks crossing through the flex lines. (You'll have to tweak it though, as my simple example will only work on taller screens. On shorter screens additional columns will be generated.)

.grid {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: center; /* key */
  height: 100vh;
  gap: 1em;
}

.grid-item {
  background-color: #ccc;
  border: 1px solid;
  height: 21%; /* prevents a 5th item in the column */
}

body {
  max-width: 1000px;
  margin: auto;
}
<div class='grid'>
  <div class='grid-item'>1</div>
  <div class='grid-item'>2</div>
  <div class='grid-item'>3</div>
  <div class='grid-item'>4</div>
  <div class='grid-item'>5</div>
  <div class='grid-item'>6</div>
  <div class='grid-item'>7</div>
</div>

CodePudding user response:

I'm guessing this is the precise result you're looking for.You can accomplish that with the Flexbox, calc() function,:nth-child() selectors,:not() pseudo-class, and, of course, @media queries.

Good luck with your work.

body {
  max-width: 1000px;
  margin: auto;
}
.flex {
  display: flex; /* displays flex-items (children) inline */
  flex-wrap: wrap; /* enables their wrapping */
}

.flex > div {
  background-color: #ccc;
  flex-basis: calc(50% - 10px); /* initial width set to 50% of the parent's - left & right margins */
  height: 100px;
  margin: 0 5px; /* preferably top & bottom margins set to zero to keep calculations simple */
  border: 1px solid;
  box-sizing: border-box; /* because of the borders, also recommended in general */
  back
}

.flex > div:nth-child(2){
  margin-top: 55px; /* half of divs height   half of the desired gap between them; modification affects all but the first div */
}

.flex > div:nth-child(odd):not(:first-child){
  margin-top: -45px; /* - half of divs height   half of the desired gap between them, so in this case the gap is 10px (2 x 5px); modification affects all but the first odd div (if ofc. modification is "")  */
}

.flex > div:nth-child(even):not(:nth-child(2)){
  margin-top: 10px; /* gap size; modification affects all but the first three divs */
}

@media (max-width: 600px){
  .flex {flex-direction: column} /* stacks flex-items vertically */
  .flex > div {flex-basis: auto} /* initial width set to default or 100% */
  .flex > div:not(:first-child) {margin-top: 10px !important}
}
<body>
<div >
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
</div>
</body>

  • Related