Flex grid with margin in between blocks


#1

Hi all

I have a codepen here - https://codepen.io/anon/pen/REdpvz

Its a simple grid using flex.

I need three columns and a margin in between each block.

This is working here but I also need the blocks to be 100% of the container so I don’t want the margin after the 3rd block.

Is it possible to have a grid like this where the blocks are a percentage and the margin on the inside and not against the container.


#2

Not sure if this is exactly what you wanted, but it’s how I interpreted it.
With flex there is no need for all that clac and nth-child business, the idea is flex does the maths for you.
I usually prefer to use flex-basis over width too.


#3

Hi

It looks like you could eliminate the right margin and use space-between


.block {
  border: 1px solid red;
  display: flex;
  flex-wrap: wrap;
  //padding: 5px 3px 5px 5px;
  max-width: 900px;
  justify-content: space-between; /*changed this*/

}

.block__item {
  background: grey;
  height: 20px;
  margin-bottom: 5px;
  width: calc(33.33% - 8px);
  /*margin-right:8px;  delete this*/
}

Edit:
Just noticed that makes the last row with two blocks have space in the center, doesn’t look too good

Looks like Sam posted seconds ahead of me


#4

That’s a side effect of space-between when the number is not a multiple of 3.
What I usually do is enable flex-grow in the line: flex: 1 0 32%; so the rows with fewer boxes grow to fill the space. Depends how you want it to handle those rows.


#5

SamA74 - this exactly what I wanted BUT I wanted the last block that is now on the right to be in the centre like in my codepen. This is possible to have the last block in the centre


#6

I think you will need to introduce a new inner wrapping div to center two blocks.

Like this…

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test Page</title>
<style>
.block {
  border: 1px solid red;
  display: flex;
  flex-wrap: wrap;
  /*padding: 5px 3px 5px 5px;*/
  max-width: 900px;
  justify-content: space-between;
}

.item {
  background: grey;
  height: 20px;
  margin-bottom: 5px;
  flex: 0 0 32%;

}
.inner {
  display:flex;
  justify-content: center;
  width: 100%;
}
.inner .item {
  flex: 0 0 32%;
  margin: 0 1%;
}
</style>

</head>
<body>

<div class="block">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="inner">
    <div class="item"></div>
    <div class="item"></div>
  </div>
</div>

</body>
</html>

#7

Here’s another way without the inner div but it adds new classes to the last two blocks.


<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Test Page</title>
<style>
.block {
  border: 1px solid red;
  display: flex;
  flex-wrap: wrap;
  /*padding: 5px 3px 5px 5px;*/
  max-width: 900px;
  justify-content: space-between;
}

.item {
  background: grey;
  height: 20px;
  margin-bottom: 5px;
  flex: 0 0 32%;

}
.left {
  margin-left:auto;
  margin-right:1%;
}
.right {
  margin-right:auto;
  margin-left:1%;
}
</style>

</head>
<body>

<div class="block">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item left"></div>
  <div class="item right"></div>
</div>

</body>
</html>

#8

Back-tracking on that, this comes close with with the last row aligned left, not centre.


#9

SamA74 Thats what I wanted, I must have not explained correctly


#10

Strange, that is how I first read it.
Then in Ray’s example the whole last row is centred, so I then thought that was the intention.

It was mainly a case of improving the maths in the calc, then the nth-child selectors to remove margins.

8 * 4 = 32 // 4  8px margins
32 / 3 = 10.6r   // between 3 items

#11

CSS grid makes this a lot easier.

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html {
	box-sizing: border-box;
}
*, *:before, *:after {
	box-sizing: inherit;
}
.grid {
	display:grid;
	grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
	grid-gap:1rem;
	max-width:1040px;
	margin:auto;
	border:1px solid red;
}
.grid > div {
	border:1px solid #000;
	min-height:100px;
	padding:10px;
}
</style>
</head>

<body>
<div class="grid">
  <div>test</div>
  <div>test</div>
  <div>test</div>
  <div>test</div>
  <div>test</div>
  <div>test</div>
  <div>test</div>
  <div>test</div>
</div>
</body>
</html>

This video is enjoyable and shows the same routine as above.