Home > Mobile >  Flex layout that puts one item on the first row and then wraps the rest on subsequent rows--all with
Flex layout that puts one item on the first row and then wraps the rest on subsequent rows--all with

Time:12-01

I have the following problem and I'm wondering if it could be solved just with CSS Flexible Box Layout:

I have a number of boxes (divs) with the same width, and I want:

  • the first box to stay in the first row
  • all other boxes on row below wrapping when necessary BUT also:
  • I want the first box to be aligned with the first boxes in the other rows.

Basically:

[]
[] [] [] 
[] [] []
[] []

and I want this behaviour no matter what the justify-content value is.

Is it possible?

CodePudding user response:

As I tried to explain in the comment I added at first to your question, using the flex layout it's based on the items size following the document flow so that if you use the property flex-basis to make it expand to full width using a selector addressing the first child only in the container, will affect its appearence.

Let's say you had cards with their own background and borders, it would screw the style if you enlarged its width for the sake of occupying the first row all by itself.

In this demo, to show how to make the first item occupy the first row, the only solution I found was using an ad hoc container for the first element only. It's not very elegant but it ensures that only that container will grow without affecting the inner content style but yet giving the layout expected.

There are possibly better solutions to solve that problem and I could see someone answering with the proposal of the grid layout that I also think would be a better bet. Unfortunately the answer was deleted as of the time I'm writing this.

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 10px;
  outline: solid 1px blue;
}

/*items in the flex container all equally sized for easy demoing*/
.flex .item{
  outline: solid 1px darkgray;
  width: 50px;
  height: 50px;
  /* the flex layout for items it's for the sake of easily center their content*/
  display: flex;
  justify-content:center;
  align-items: center;
}

.flex > *:first-child {
  outline: solid 1px red;
  flex-basis: 100%;
}
<div >
  <!-- the first item was wrapped in its own div so that only that will change its width to occupy the whole row preventing its inner child to change dimensions -->
  <div>
    <div >1</div>
  </div>
  <div >2</div>
  <div >3</div>
  <div >4</div>
  <div >5</div>
  <div >6</div>
  <div >7</div>
  <div >8</div>
  <div >9</div>
  <div >10</div>
  <div >11</div>
  <div >12</div>
  <div >13</div>
  <div >14</div>
  <div >15</div>
  <div >16</div>
</div>

CodePudding user response:

This will probably not work with all the justify-content values but it gives you the separation you want.

.box {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.box div {
  width: 80px;
  aspect-ratio: 1;
  background: red;
}

/* the pseudo element will be the separator */
.box:before {
  content:"";
  flex-basis:100%;
}
/* the first element before it*/
.box div:first-child {
  order: -1;
}
<div >
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

  • Related