Reputation: 18805
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
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