Search code examples
htmlcssflexboxcss-multicolumn-layout

Why does my column gap get smaller when I increase the width of my container?


I'm having a hard time understanding the logic behind the column gap in a multi-column layout. I have the following HTML/CSS in this Fiddle:

<div class="flex-container">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
</div>
.flex-container {
  height: 500px;
  width: 300px;
  border: 1px solid blue;
  columns: 120px;
  padding: 10px;
}

.flex-item {
  background: OliveDrab;
  padding: 5px;
  width: 100px;
  height: 100px;
  line-height: 100px;
  color: white;
  text-align: center;
  break-inside: avoid-column;
}

You will notice that if you change the width of the container from 300px to 400px, the gap between the columns actually shrinks.

enter image description here

Why is it doing this? Is it possible to left-align the columns so they don't move around? Fixed gap between CSS columns may suggest that's not possible.


Solution

  • The column layout is a bit tricky. If you read the specification related to column-width you can find:

    describes the optimal column width. The actual column width may be wider (to fill the available space), or narrower (only if the available space is smaller than the specified column width). ref

    Remove the width from the elements and resize the container to notice this:

    .flex-container {
      width: 400px;
      border: 1px solid blue;
      columns: 120px;
      padding: 10px;
      overflow:hidden;
      resize:horizontal;
    }
    
    .flex-item {
      background: OliveDrab;
      padding: 5px;
      height: 100px;
      line-height: 100px;
      color: white;
      text-align: center;
      break-inside: avoid-column;
    }
    <div class="flex-container">
      <div class="flex-item">1</div>
      <div class="flex-item">2</div>
    </div>

    You will notice that the gap is indeed fixed but the width of columns is changing.

    You can find more details around the algorithm here: https://drafts.csswg.org/css-multicol-1/#pseudo-algorithm


    A solution is to consider the use of CSS grid having fixed column width. The trick is to define the width of the grid column to be equal to the gap+width of column and you make you container fill all the columns (its width will be a multiplier of gap+width of column)

    Resize the screen to see the result:

    .container {
      display:grid;
      grid-template-columns:repeat(auto-fit,140px); /* 120 + 20 */
      overflow: hidden;
      resize: horizontal;
      border: 1px solid blue;
    
    }
    
    .flex-container {
      grid-column:1/-1;
      column-width: 120px;
      column-gap: 20px;
      padding: 10px;
    }
    
    .flex-item {
      background: OliveDrab;
      padding: 5px;
      height: 100px;
      line-height: 100px;
      color: white;
      text-align: center;
      break-inside: avoid-column;
    }
    <div class="container">
      <div class="flex-container">
        <div class="flex-item">1</div>
        <div class="flex-item">2</div>
        <div class="flex-item">3</div>
        <div class="flex-item">4</div>
        <div class="flex-item">5</div>
        <div class="flex-item">6</div>
        <div class="flex-item">7</div>
        <div class="flex-item">8</div>
        <div class="flex-item">9</div>
        <div class="flex-item">10</div>
      </div>
    </div>