Home > Net >  Getting CSS columns to bunch on the left instead of spreading out
Getting CSS columns to bunch on the left instead of spreading out

Time:07-05

How do I get CSS columns to not spread out but instead bunch on the left

What I get

enter image description here

What I want

enter image description here

Example

body {
  background-color: #c3dbff;
}
.cols {
  columns: 250px;  /* want however many 250px columns will fit */
}
.thing {
  display: inline-block;
  width: 240px;
  background: red;
  margin-bottom: 10px;
  break-inside: avoid-column;
  
  
  /* below just to make it clear the order of children in the columns */
  color: white;
  display: inline-grid;
  place-content: center;
  font-weight: bold;
  font-family: sans-serif;
  font-size: 50pt;
}
<div >
  <div  style="height: 200px;">1</div>
  <div  style="height: 200px;">2</div>
  <div  style="height: 290px;">3</div>
  <div  style="height: 280px;">4</div>
  <div  style="height: 200px;">5</div>
  <div  style="height: 230px;">6</div>
  <div  style="height: 260px;">7</div>
  <div  style="height: 210px;">8</div>
  <div  style="height: 280px;">9</div>
  <div  style="height: 230px;">10</div>
  <div  style="height: 260px;">11</div>
  <div  style="height: 210px;">12</div>
  <div  style="height: 200px;">13</div>
  <div  style="height: 270px;">14</div>
  <div  style="height: 220px;">15</div>
  <div  style="height: 260px;">16</div>
  <div  style="height: 250px;">17</div>
  <div  style="height: 290px;">18</div>
</div>

CSS only.

Things I tried,

  • setting column-width: 250px. ❌

  • setting the outer container to display: inline-block;

  • setting the outer container to margin: 0 auto 0 0

  • setting column-gap: 10px

  • setting display: flex; flex-direction: column; flex-wrap: wrap

    This doesn't work because in order to wrap I'd have to give the flex box a height, otherwise it has no idea it needs to wrap. That's different that columns which will figure out height after figuring out how many columns.

One thing that makes it hard to find an answer is most results about columns are not about the css columns property but about columns in tables, or grids, or flexbox

PS: No, I'm not trying to do a masonry layout out. I want the items to go down the first column, then flow into the second (vs masonry where they flow to the right first and then fill in the shortest column. not looking for that).

CodePudding user response:

It seems your items has fixed sizes so you can use CSS grid to fix this. The trick is to create as many columns with fixed width as possible and span all of them using grid-column: 1/-1

body {
  background-color: #c3dbff;
}


.wrapper {
  display:grid;
  grid-template-columns:repeat(auto-fit,250px); /* same as column width */
  gap:10px; /* same as column gap */
}

.cols {
  columns: 250px;
  column-gap: 10px;
  grid-column:1/-1; /* take all the columns of the grid*/
}

.thing {
  display: inline-block;
  width: 100%; /* use 100% and rely on the gap */
  background: red;
  margin-bottom: 10px;
  break-inside: avoid-column;
  color: white;
  display: inline-grid;
  place-content: center;
  font-weight: bold;
  font-family: sans-serif;
  font-size: 50pt;
}
<div >
  <div >
    <div  style="height: 200px;">1</div>
    <div  style="height: 200px;">2</div>
    <div  style="height: 290px;">3</div>
    <div  style="height: 280px;">4</div>
    <div  style="height: 200px;">5</div>
    <div  style="height: 230px;">6</div>
    <div  style="height: 260px;">7</div>
    <div  style="height: 210px;">8</div>
    <div  style="height: 280px;">9</div>
    <div  style="height: 230px;">10</div>
    <div  style="height: 260px;">11</div>
    <div  style="height: 210px;">12</div>
    <div  style="height: 200px;">13</div>
    <div  style="height: 270px;">14</div>
    <div  style="height: 220px;">15</div>
    <div  style="height: 260px;">16</div>
    <div  style="height: 250px;">17</div>
    <div  style="height: 290px;">18</div>
  </div>
</div>

CodePudding user response:

Update:

Actually this solution doesn't work. The problem is just because the column size is N and the outer size is N * 3 does not mean the browser will chose to make 3 columns. For example, if there are only 2 items it will make 2 columns because why make 3? But when it makes 2 it ends up distributing the space. So this isn't a solution AFAICT.

Previous answer:

I did think of one poor solution. If container queries worked then I could make

<div id="outer">
  <div id="inner">
    <div></div>
    <div></div>
    <div></div>
  </div>
</div>

And then do queries on outer to force inner to only be multiples of the size I want the columns.

Since I don't have container queries, then I can use media queries. It kind of sucks because I can't use calc and it only works if the out container can be fit to the page.

body {
  background-color: #c3dbff;
  margin: 0;
}
.cols {
  columns: 250px;  /* want however many 250px columns will fit */
  column-gap: 0px;
}
.thing {
  display: inline-block;
  width: 240px;
  background: red;
  margin-bottom: 10px;
  break-inside: avoid-column;
  
  /* below just to make it clear the order of children in the columns */
  color: white;
  display: inline-grid;
  place-content: center;
  font-weight: bold;
  font-family: sans-serif;
  font-size: 50pt;
}

@media (max-width: 2249px) { .cols { width: 2000px; } }
@media (max-width: 1999px) { .cols { width: 1750px; } }
@media (max-width: 1749px) { .cols { width: 1500px; } }
@media (max-width: 1499px) { .cols { width: 1250px; } }
@media (max-width: 1249px) { .cols { width: 1000px; } }
@media (max-width: 999px) { .cols { width: 750px;   } }
@media (max-width: 749px) { .cols { width: 500px;   } }
@media (max-width: 499px) { .cols { width: 250px;  margin-right: 10px; } }
<div >
  <div  style="height: 200px;">1</div>
  <div  style="height: 200px;">2</div>
  <div  style="height: 290px;">3</div>
  <div  style="height: 280px;">4</div>
  <div  style="height: 200px;">5</div>
  <div  style="height: 230px;">6</div>
  <div  style="height: 260px;">7</div>
  <div  style="height: 210px;">8</div>
  <div  style="height: 280px;">9</div>
  <div  style="height: 230px;">10</div>
  <div  style="height: 260px;">11</div>
  <div  style="height: 210px;">12</div>
  <div  style="height: 200px;">13</div>
  <div  style="height: 270px;">14</div>
  <div  style="height: 220px;">15</div>
  <div  style="height: 260px;">16</div>
  <div  style="height: 250px;">17</div>
  <div  style="height: 290px;">18</div>
</div>

Apparently, at least in Chrome, when the column goes to a single column the margin-bottom setting is ignored.

CodePudding user response:

try using display flex. set up justify-content to flex-start, align items to the centre and flex-wrap to wrap. and give a justifiable width and avoid using inline styles.

CodePudding user response:

What happens here is defined in the docs of column-width

The actual column width may differ from the specified value: it may be wider when necessary to fill available space

So the priority is to fill the entire container with as many columns as possible, not to keep the column at a certain desired width. If what you want is equal width gutters (but sometimes too wide items), you can set the column-gap to 10px and item width to 100%.

  • Related