Joshua Ohana
Joshua Ohana

Reputation: 6131

How to set outer padding / margin on a flex row?

I have several flex rows which I want to set an outer margin or padding on, so that the contents for example will not reach within 50px of the screen edge.

I have tried all manner of messing with width, min-width, and flex-basis to get this to work. Every time I get something approaching correct the contents become misaligned for some reason, and/or a bunch of content spills outside of the viewport.

When not using flex-box this is very simple by just settings margin: auto 50px; on the row, but with flex-box I cannot seem to make it work.

Flex settings I am using are:

div {
  position: absolute;
  width: 100%;
  display: flex;
  justify-content: center;
  flex-direction: row;
  justify-content: space-between;
}
div:nth-of-type(1) {
  top: 10%;
  margin: 0;
}
div:nth-of-type(2) {
  top: 20%;
  margin: auto 50px;
}
<div>
  <p>1</p>
  <p>2</p>
  <p>3</p>
  <p>4</p>
</div>

<div>
  <p>1</p>
  <p>2</p>
  <p>3</p>
  <p>4</p>
</div>

jsfiddle

In this example I would want the second row to behave just like the first, having everything nice and centered-aligned, but with the contents inside the original viewport with the simple change of 50px of margin added on the outside of the second row.

update

Also now have tried messing with adding two "spacer" flex items within that row on the outsides with min-width or flex-basis, but this also doesn't produce the desired result.

Basically, I want everything to shrink down instead of reaching the borders, keeping a certain width away from the edge of the viewport, and then at a certain point to break into two rows.

Upvotes: 2

Views: 3298

Answers (2)

Michael Benjamin
Michael Benjamin

Reputation: 371699

It's not flexbox that's messing up the margin. It's position: absolute.

When you remove an element from the document flow, it doesn't care about surrounding box properties (like content, padding and margin). It goes right through them.

An alternative method is to set a maximum width for each container.

Then center them horizontally.

body {
  position: relative;
  height: 100vh;
  margin: 0;
}
div {
  position: absolute;
  display: flex;
  justify-content: space-between;
  width: 80%;
  left: 50%;
  transform: translateX(-50%);
  background-color: yellow;
}
div:nth-of-type(1) { top: 10%; }
div:nth-of-type(2) { top: 25%; }
div > p {
  flex: 1;
  text-align: center;
  border: 1px dashed black;
}
<div>
  <p>1</p>
  <p>2</p>
  <p>3</p>
  <p>4</p>
</div>
<div>
  <p>1</p>
  <p>2</p>
  <p>3</p>
  <p>4</p>
</div>

revised fiddle

Upvotes: 2

cjl750
cjl750

Reputation: 4629

First, some notes:

  1. You don't need the absolute positioning to get the alignment you want in your fiddle, unless you have that for some other reason.
  2. You have a couple of justify-content properties set. You can delete the justify-content: center one.
  3. You also don't necessarily need to specify 100% width for the divs as using a flex display will automatically make those divs fill empty space around them.
  4. Also, you don't need to specify flex-direction: row unless you're trying to overwrite another style. Row is the default.

So once we've simplified the CSS a bit, it just becomes a matter of adding in the margin or padding. You can give the divs a simple margin, such as margin: 50px, or, if you want to create the effect of a box around the whole group of content without actually having a container in your markup, you can give all rows the same left and right margins while giving the first one a top margin and the last one a bottom margin.

Example of that latter scenario, using markup from your fiddle:

HTML:

<div>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>

<div>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
</div>

CSS:

div {
  display: flex;  
  justify-content: space-between;
}
div:nth-of-type(1) {
  margin: 50px 50px 0 50px;
}
div:nth-of-type(2) {
  margin: 0 50px 50px 50px;
}

More reading: W3Schools Flexbox guide, CSS Tricks guide with nice illustrations

Upvotes: 2

Related Questions