mahemoff
mahemoff

Reputation: 46399

Collapsing margin on Flexbox children

I have the following arrangement via flexbox with flex-wrap and elements able to stretch using flex-grow:

flexbox

Each item has a margin on all sides. This is to separate the items from each other, but the side effect is the whole block has margins which I'd like to collapse. It could be done with rules like nth-child(-n+3) { margin-top: 0; } but because the container size could vary, there could be any number of items per row and any number of rows. So I'm wondering if flex-box has any way to collapse the outer margins in a setup like this, while retaining the margins between items.

JSBin

The HTML is simply 6 items inside a container.

The CSS (Sass) is as follows:

.container
  display: flex
  flex-wrap: wrap
  background: #eef
  align-items: stretch

.item
  flex-grow: 1  
  margin: 1em
  border: 1px solid black
  padding: 1em
  min-width: 6em

Upvotes: 10

Views: 8510

Answers (2)

Jérôme Beau
Jérôme Beau

Reputation: 11450

Another hack is to split the margin responsibilities between container and item, each caring about half (say $margin is 1em):

container cares about its bottom margin and half left + half-right of items:

.container {
   width: 100%;
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;           // Go to next line if not enough space
   padding-top: 0;            // Let items handle top
   padding-left: $margin/2;   // Handle half of left
   padding-bottom: $margin;   // Handle bottom
   padding-right: $margin/2;  // Handle half of right
}

items care about top and half left + half right:

.item {
   flex-grow: 1;             // Use available space
   margin-left: $margin/2;   // Handle other half of left
   margin-right: $margin/2;  // Handle other half of right
   margin-top: $margin;      // Handle top
}

Regarding items size, you can set a width if you want items to look the same.

.item.fixed {
   width: 15em;
}

See a demo here.

Upvotes: 0

dholbert
dholbert

Reputation: 11839

It's a bit of a hack, but you can add a negative margin on the flex container to cancel out the items' margins along the edges, and then move its "background" styling to a parent wrapper-element.

Updated JSBin

Updated CSS (SASS):

.wrapper
  background: #eef
  border: 1px solid darkgray

.container
  display: flex
  flex-wrap: wrap
  margin: -1em

.item
  flex-grow: 1  
  margin: 1em
  border: 1px solid black
  padding: 1em
  min-width: 6em

Upvotes: 6

Related Questions