2

I'm trying to wrap elements in a column direction. My first element is 100% wide and all other elements are 50% wide. When it comes time to wrap, the last few elements wrap beginning from the first element that is 100% wide instead of going down to the second line.

JSFiddle link: https://jsfiddle.net/e4j16apg/

This is what I'm trying to achieve: enter image description here

.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  box-sizing: border-box;
  height: 200px;
  width: 50%;
  border: 1px solid blue;
}

.ca {
  width: 50%;
  border: 1px solid red;
}

.ca-1 {
  height: 50px;
  width: 100%;
  border: 1px solid green;
}
<div class="container">
  <div class="ca ca-1">ca-1</div>
  <div class="ca ca-2">ca-2</div>
  <div class="ca ca-3">ca-3</div>
  <div class="ca ca-3">ca-3</div>
  <div class="ca ca-4">ca-4</div>
  <div class="ca ca-5">ca-5</div>
  <div class="ca ca-6">ca-6</div>
  <div class="ca ca-7">ca-7</div>
  <div class="ca ca-8">ca-8</div>
  <div class="ca ca-9">ca-9</div>
  <div class="ca ca-10">ca-10</div>
</div>

Thank you so much!

disinfor
  • 10,865
  • 2
  • 33
  • 44
c f
  • 196
  • 2
  • 14

2 Answers2

2

You can't achieve what you want with flexbox, but you can using columns (and making the first element span all columns):

.container {
  columns: 2;
  width: 50%;
  border: 1px solid blue;
  column-gap: 0;
  /* height: 200px; */
}

.ca {
  border: 1px solid red;
  break-inside: avoid;
  /* height: calc(100% / 6); */
}

.ca-1 {
  column-span: all;
}

* {
  box-sizing: border-box;
}
<div class="container">
  <div class="ca ca-1">ca-1</div>
  <div class="ca ca-2">ca-2</div>
  <div class="ca ca-3">ca-3</div>
  <div class="ca ca-3">ca-3</div>
  <div class="ca ca-4">ca-4</div>
  <div class="ca ca-5">ca-5</div>
  <div class="ca ca-6">ca-6</div>
  <div class="ca ca-7">ca-7</div>
  <div class="ca ca-8">ca-8</div>
  <div class="ca ca-9">ca-9</div>
  <div class="ca ca-10">ca-10</div>
</div>

Also note that, by default, columns calculates the total height of all children that wrap and wraps as close as possible to half (when there're two). So you don't actually need a fixed height for it. And you don't need the height set on children, especially if they have uneven heights.

CSS columns are designed to layout as newspaper columns out of the box, which seems to be what you're after.

To prevent breaks inside children, use break-inside: avoid;.

tao
  • 82,996
  • 16
  • 114
  • 150
  • 1
    The problem is that the OP wants 2-6 in the first column and then 7-10 in the second. I don't think this can be achieved using `flex-box` without adding additional markup (e.g. wrapping or grouping divs) – disinfor Oct 16 '19 at 19:55
  • 1
    @disinfor, you're right. I edited my answer accordingly. Thanks for pointing it out. – tao Oct 16 '19 at 20:18
1

You wrote:

When it comes time to wrap, the last few elements wrap beginning from the first element that is 100% wide instead of going down to the second line.

That's the problem. You believe there is a "second line". There isn't.

Once you make your first element take 100% width, you've defined the width of the column.

By making the subsequent elements 50% width, you're telling them to consume 50% of that column.

The elements that wrap create a second column.

They can't wrap under the 100% element and next to the first set of 50% elements because you can't make elements wrap onto the same line.

So you don't have to change your HTML, use CSS Grid for the layout:

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(9, 1fr);
  grid-auto-flow: column;
  box-sizing: border-box;
  height: 200px;
  width: 50%;
  border: 1px solid blue;
}

.ca {
  border: 1px solid red;
}

.ca-1 {
  grid-column: 1 / -1;
  grid-row: 1 / 3;
  border: 1px solid green;
}
<div class="container">
  <div class="ca ca-1">ca-1</div>
  <div class="ca ca-2">ca-2</div>
  <div class="ca ca-3">ca-3</div>
  <div class="ca ca-3">ca-3</div>
  <div class="ca ca-4">ca-4</div>
  <div class="ca ca-5">ca-5</div>
  <div class="ca ca-6">ca-6</div>
  <div class="ca ca-7">ca-7</div>
  <div class="ca ca-8">ca-8</div>
  <div class="ca ca-9">ca-9</div>
  <div class="ca ca-10">ca-10</div>
</div>

More details here:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701