Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flex wrap-reverse with normal content order?

Tags:

html

css

flexbox

I have three boxes that I'd like to put in various combinations into a container. A box will sometimes be present in a combination, sometimes not.

If all three boxes are in the container, there should be a full-width box on top, and two half-width boxese in a row underneath.

If two boxes are in the container, there should only be two half-width boxes.

If there is one box, it should be full-width.

I came up with a solution which uses wrap: wrap-reverse, but it requires you to put elements in reverse order in your html. Minor annoyance.

So I used flex-direction: row-reverse and order to reverse the order of the content.

I have a small problem with this solution because using order makes for a less flexible solution if we want to let the same css handle 5 boxes, for instance.

Right now I'm leaning toward not using order and just living with the reversed html. What do you think? Am I missing a silver bullet somewhere?

https://jsfiddle.net/uesje5dq/

.container {
  display: flex;
  flex-wrap: wrap-reverse;
  flex-direction: row-reverse;
}

.item {
  flex: 1;
  flex-basis: 50%;
}

.item:nth-child(1) {
  order: 3;
}

.item:nth-child(2) {
  order: 2;
}

.item:nth-child(3) {
  order: 1;
}

===========================================================================

<!DOCTYPE html>
<html lang="en">
<head>
  <link rel="stylesheet" type="text/css" href="style.css"> 
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
  </div>
</body>
</html>
like image 704
Matt Broatch Avatar asked Jan 20 '18 22:01

Matt Broatch


1 Answers

If you combine the first-child and nth-last-child you can count the amount of children, like this, where if there is only 1 or 3, the first is full width, otherwise they are half wide.

And the .item:first-child:nth-last-child(3) rule works like that, when the first child is also the 3rd from the end, we know there is 3 items, and the rule kicks in.

Stack snippet

.container {
  display: flex;
  flex-wrap: wrap;
}

.item:only-child,
.item:first-child:nth-last-child(3) {
  flex-basis: 100%;
}

.item {
  flex-basis: 50%;
}
  <div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
  </div>
<hr>
  <div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
  </div>
<hr>
  <div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
  </div>

With this logic you can also check if there is 5, and when, make the first full width and the rest half.

Stack snippet

.container {
  display: flex;
  flex-wrap: wrap;
}

.item:only-child,
.item:first-child:nth-last-child(3),
.item:first-child:nth-last-child(5) {
  flex-basis: 100%;
}

.item {
  flex-basis: 50%;
}
<div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: yellow;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: purple;"></div>
  </div>

Or on an unknown amount of items, and when an uneven amount, the first has full width and the rest half.

Stack snippet

.container {
  display: flex;
  flex-wrap: wrap;
}

.item:first-child:nth-last-child(odd) {
  flex-basis: 100%;
}

.item {
  flex-basis: 50%;
}
<div>9 items</div>

<div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: yellow;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: purple;"></div>

    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: yellow;"></div>
  </div>
  
<div><br>7 items</div>

<div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: yellow;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: purple;"></div>

    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
  </div>

<div><br>6 items</div>

<div class="container">
    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: green;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: blue;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: yellow;"></div>
    <div class="item" style="height: 100px;width:100%;background-color: purple;"></div>

    <div class="item" style="height: 100px;width:100%;background-color: red;"></div>
  </div>
  

And here is few more interesting ways to count the amount of children:

  • FlexBox align (stretch) last Item

  • Can CSS detect the number of children an element has?

like image 145
Asons Avatar answered Sep 30 '22 09:09

Asons