Zze
Zze

Reputation: 18805

flexbox prevent wrapping of rows

I have the following snippet in which when you click one of the red boxes, its width doubles in size. The functionality that I want to achieve is that when the width increases, the other boxes in that row shrink to stop the wrapping of a box to a new 3rd line.

$('.card').click(function() {
  if ($('.card.selected')[0] != this)
    $('.card.selected').toggleClass('selected', false);

  $(this).toggleClass('selected');
})
section {
  display: flex;
  flex: 1 1 100%;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  width: 100%;
}

.card {
  display: block;
  width: calc(25% - 2px);
  height: 40px;
  background-color: #f00;
  margin: 1px;
  -webkit-transition: .15s;
  transition: width .15s;
}

.selected {
  width: calc(50% - 2px);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<section>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</section>

I am able to achieve the desired functionality by literally wrapping each row in individual flexboxs, however I want to know if there is a css approach which will not require this. The reason being that the boxes are being dynamically toggled on and off, and I want them to "flow" as you would expect and explicitly defining the rows makes this much more awkward.

Upvotes: 2

Views: 322

Answers (1)

G-Cyrillus
G-Cyrillus

Reputation: 105863

If you have 2 or maximum 3 rows, you can use pseudo :before and/or :after to force new lines. flex:1; should evenly dispatch the children on each rows. You can also use a min-width to easily add a transition.

This technic allows you to draw 3 rows without extra markup. to draw more rows, use a new container or insert elements to break the lines the same way the pseudo does.

example with 2 rows

section {
display:flex;
flex-wrap:wrap;
}
div {
  flex:1;
  min-width:calc(16.66% - 2px);
  transition:0.5s; 
  margin:auto;
  height: 40px;
  background-color: #f00;
  margin: 1px;
  -webkit-transition: 0.15s;
  transition: width 0.15s;
  order:0;
}
div:nth-child(4)~div {/* every div starting from the fith */
  order:2;
}
section:before{
  content:'';
  width:100%; /* fill a whole row */
  order:1;/* comes before the fith div*/ 
}
div:focus {/* css demo purpose instead js onclick event */
  min-width:calc(50% - 2px);
  transition:0.5s; 
  background-color:yellow
}



div {display:flex;align-items:center;justify-content:center;}
section {counter-reset: div}
section div:before {counter-increment:div;content:'DIV N°: 'counter(div);}
<section>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
</section>

example with 3 rows :

section {
display:flex;
flex-wrap:wrap;
}
div {
  flex:1;
  min-width:calc(16.66% - 2px);
  transition:0.5s; 
  margin:auto;
  height: 40px;
  background-color: #f00;
  margin: 1px;
  -webkit-transition: 0.15s;
  transition: width 0.15s;
  order:0;
}
div:nth-child(4)~div {
  order:2;
}
div:nth-child(8)~div {
  order:4;
}
section:before,
section:after{
  content:'';
  width:100%;
  order:1;
}
section:after {
  order:3;
}
div:focus {
  min-width:calc(50% - 2px);
  transition:0.5s; 
  background-color:yellow
}

div {display:flex;align-items:center;justify-content:center;}
section {counter-reset: div}
section div:before {counter-increment:div;content:'DIV N°: 'counter(div);}
<section>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
  <div tabindex="0"></div>
</section>

Upvotes: 2

Related Questions