Roland Seuhs
Roland Seuhs

Reputation: 1995

Set wrapping priority between primary and nested flex containers

I have a flexbox within a flexbox (JSFiddle):

The problem is that the items in the left div start to wrap earlier than necessary (the left div still has room to shrink).

The inner flexbox should only wrap after the outer flexbox has wrapped - as long as there is still space for the outer flexbox, the inner flexbox should not wrap and the outer flexbox should shrink, instead.

I tried to give .b_row a width of 100%, but that didn't work.

.m {
  display: flex;
  flex-wrap: wrap;
}
.l_1 {
  background-color: red;
  flex: 1;
  padding: 15px;
  margin-left: auto;
  margin-right: auto;
}
.r_1 {
  background-color: yellow;
  flex: 1;
  padding: 25px;
  margin-left: auto;
  margin-right: auto;
}
.b_1 {
  padding: 15px;
  border-radius: 4px;
}
.b_row {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}
.b_item {
  flex: 1;
}
<div class=m>
  <div class=l_1>
    <div class=b_1>
      Left text
      <div class=b_row>
        <div class=b_item>Item 1
          <br>
          <input class=datepicker type=text size=10>
        </div>
        <div class=b_item>Item 2
          <br>
          <input class=datepicker type=text size=10>
        </div>
      </div>
    </div>
   </div>
  <div class=r_1>Right Item</div>
</div>

Upvotes: 11

Views: 4176

Answers (4)

vals
vals

Reputation: 64164

You can control the wrapping behaviour using flex-basis in the inner elements.

(Solution without media queries)

.outer {
  display: flex;
  flex-wrap: wrap;
  border: solid 1px red;
  padding: 10px;
}

.inner {
  display: flex;
  flex-wrap: wrap;
  border: solid 1px blue;
  padding: 10px;
  flex-basis: 200px;
  flex-grow: 1;
}

.left {
  flex-basis: 100px;
  flex-grow: 1;
}

#right {
  flex-basis: 100px;
  flex-grow: 1;
  border: solid 1px green;
}

#o1 {
  width: 400px;
}

#o2 {
  width: 300px;
}

#o3 {
  width: 200px;
}
<div class="outer" id="o1">
  <div class="inner">
    <div class="left">Left 1</div>
    <div class="left">Left 2</div>
  </div>
  <div id="right">Right</div>
</div>

<div class="outer" id="o2">
  <div class="inner">
    <div class="left">Left 1</div>
    <div class="left">Left 2</div>
  </div>
  <div id="right">Right</div>
</div>

<div class="outer" id="o3">
  <div class="inner">
    <div class="left">Left 1</div>
    <div class="left">Left 2</div>
  </div>
  <div id="right">Right</div>
</div>

Upvotes: 3

Upendra Nath Dubey
Upendra Nath Dubey

Reputation: 76

using a media query to control the wrapping behavior. Certainly, media queries will give you more control - especially when it comes to spacing elements apart from each other. check the code

body{
  box-sizing:border-box;
}
.m {
  display: flex;
  flex-wrap: wrap;
}
.l_1 {
  background-color: red;
  flex: 1;
  padding: 15px;
  margin-left: auto;
  margin-right: auto;
}
.r_1 {
  background-color: yellow;
  flex: 1;
  padding: 25px;
  margin-left: auto;
  margin-right: auto;
}
.b_1 {
  padding: 15px;
  border-radius: 4px;
}
.b_row {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}
.b_item {
  flex: 1;
}

.b_item .datepicker{
  width:calc(100% - 20px);
  margin:0px 10px 0 0;
}

.b_item:last-child .datepicker{
  margin-right:0;
}

@media screen and (max-width:480px){
  .m, .b_row{
    flex-direction:column;
  }
  
  .b_item .datepicker{
    width:100%;
    margin:0 0px 10px;
  }
  .r_1, .l_1{
      margin:0;
  }
}
<div class=m>
  <div class=l_1>
    <div class=b_1>
      Left text
      <div class=b_row>
        <div class=b_item>Item 1
          <br>
          <input class=datepicker type=text size=10>
        </div>
        <div class=b_item>Item 2
          <br>
          <input class=datepicker type=text size=10>
        </div>
      </div>
    </div>
   </div>
  <div class=r_1>Right Item</div>
</div>

Upvotes: 0

jottin
jottin

Reputation: 419

Certainly media queries will give you more control - especially when it comes to spacing elements apart from each other. I could only take it so far using CSS grid without media queries...

More about that here: https://css-tricks.com/look-ma-no-media-queries-responsive-layouts-using-css-grid/

and the basics: https://css-tricks.com/almanac/properties/g/grid-template-columns/

Resize demonstration gif

<div class=m>
  <div class=l_1>
    <div class=b_1>
      Left text
      <div class=b_row>
        <div class=b_item>Item 1
          <br>
          <input class=datepicker type=text size=10>
        </div>
        <div class=b_item>Item 2
          <br>
          <input class=datepicker type=text size=10>
        </div>
      </div>
    </div>
  </div>
  <div class=r_1>Right Item</div>
</div>

.m {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  grid-auto-rows: 200px;
  margin: 0 auto;
  overflow: hidden;
  box-sizing: border-box;
  border: 1px solid red;
  width: 100%;
}

.l_1 {
  background-color: #ddd;
  padding: 1em;
  margin: 0 auto;
  border: 1px solid red;
  width: 100%;
  grid-column: 1/3;
}

.r_1 {
  background-color: #eee;
  padding: 2em;
  margin: 0 auto;
  margin-left: 0;
  border: 1px solid red;
  width: 100vw;
}

.b_1 {
  padding: 1em;
  /*border-radius: 4px;
  background-color: #febb02;
    border-color: #e2aa11;
  background-color: <? e($_COLORS['emph']);
  ?>;
  border: 1px solid <? e($_COLORS['emph_dark']);
  ?>;*/
}

.b_row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  margin: 0 auto;
  padding-right: 2.2em;
  border: 1px solid red;
  width: 100%;
}

.b_item {
  border: 1px solid red;
  max-width: calc(100% - 10px);
}

.b_item input {
  width: 90%;
}

https://jsfiddle.net/z8swumkh/1/

Upvotes: 1

Michael Benjamin
Michael Benjamin

Reputation: 371203

Consider using a media query to control the wrapping behavior of the inner flex container.

Instead of this:

.b_row {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}

Try something along these lines:

.b_row {
  display: flex;
  /* flex-wrap: wrap; */
  width: 100%;
}

@media ( max-width: 300px ) {
   .b_row { flex-wrap: wrap; }
}

revised fiddle

Upvotes: 0

Related Questions