How can I get buttons inside a div inside a row to wrap? (flex and angular)

Viewed 1145

So I've got a kind of header, that contains a heading and a bunch of buttons. These buttons can be added to, so it's important to me that they wrap properly.

The catch is that these buttons are fed in via angular as an outside component, and as such they get put in a div (I'm assuming?)

In this codepen I have illustrated the result I want to reach (blue) vs. what I'm getting (red). It's hard to see on the snippet so here is a link to a codepen. To be clear, I want the buttons to wrap individually, one by one, rather than as a group.

.flex-row {
  display: flex;
  flex-flow: row wrap;
}

.red {
  background: red;
}

.blue {
  background: blue;
}
<div class="flex-row red">
  <h1>Really long annoying header goes here</h1>
  <div>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
  </div>
</div>

<div class="flex-row blue">
  <h1>Really long annoying header goes here</h1>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
</div>

By the way, here is the component selection-buttons.component.html:

<button class="selectionbtn selectbtn" *ngFor="let btn of input.items;let idx = index" (click)="onSelect(idx)" [ngClass]="{'first': idx === 0, 'last': idx === input?.items?.length -1, 'active': currIndex === idx }" value="idx">{{btn.label | translate}}</button>

I made sure to remove the div they were being generated inside, which made me think that when gets called, they would just be generated inside the current div, but it doesn't seem to be the case.

3 Answers

With block like elements, as flex items are, browsers will start wrapping the outer one's first and the inner one's last.

Knowing that, one possible solutions it to make all children inline elements, which also mean the display: flex needs to be removed from the outer most parent.

Updated codepen

Stack snippet

.flex-row {
  /*display: flex;
  flex-flow: row wrap;*/
}

.flex-row * {
  display: inline;
}

.red {
  background: red;
}

.blue {
  background: blue;
}
<div class="flex-row red">
  <h1>Really long annoying header goes here</h1>
  <div>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
  </div>
</div>

<div class="flex-row blue">
  <h1>Really long annoying header goes here</h1>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
</div>

This is possible with flexbox but only by using a poorly supported property on the inner div.

display: contents;

These elements don't produce a specific box by themselves. They are replaced by their pseudo-box and their child boxes.

MDN

Support is essentially, Chrome (58+) & FF (37+)

Note: Up to Chrome 63 ("In Chrome, the contents value is currently disabled by default, but can be enabled with the "Experimental Web Platform features" flag.")

.flex-row {
  display: flex;
  flex-flow: row wrap;
  align-items: center;
}

.red {
  background: red;
}

.red div {
  display: contents;
}
<div class="flex-row red">
  <h1>Really long header goes here</h1>
  <div>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
  </div>
</div>

Give display:flex to button wrap div class like:

.red div{
  display:flex;
}

Note : Please check in full page.

.flex-row {
  display: flex;
  flex-flow: row wrap;
}
.red {
  background: red;
}
.blue {
  background: blue;
}
.red div{
  display:flex;
}
<div class="flex-row red">
  <h1>Really long annoying header goes here</h1>
  <div>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
  </div>
</div>

<div class="flex-row blue">
  <h1>Really long annoying header goes here</h1>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
    <button>button</button>
</div>

Related