cssgrid

Why does grid-column add an extra row?


I’m trying to understand what’s happening with the grid-column property in what’s supposed to be a single row.

I have a simple grid of four items with grid-template-columns, where I want to reverse the last two. I have defined the grid with a single row with grid-template-rows. I position them using individual grid-column properties.

div#buttons {
  display: grid;
  grid-template-columns: auto auto auto auto;
  grid-template-rows: auto;
  button#one {
    grid-column: 1/2;
  }
  button#two {
    grid-column: 2/3;
  }
  button#three {
    grid-column: 4/5;
  }
  button#four {
    grid-column: 3/4;
    /* grid-area: 1/3/2/4; */
  }
}
<div id="buttons">
  <button id="one">One</button>
  <button id="two">Two</button>
  <button id="three">Three</button>
  <button id="four">Four</button>
</div>

When I run this, I find that the last two items are reversed, but the last item, now in the 3rd position, has dropped to the next line.

I thought that using grid-column would simply apply their column position, and I can’t see where the extra line comes from.

If I use the commented-out grid-area property which forces the list item in the first and only row, then it works as planned.

There’s nothing I can find in the documentation which explains this.


Solution

  • The default grid-auto-flow value uses an auto-placement algorithm that tries to maintain the normal reading order of the elements, i.e. reading left-to-right and then top to bottom in western documents. So since button #four is after button #three in the DOM document, to maintain that order it must be placed on a new row.

    You can change this auto-placement choice by adding grid-auto-flow: dense;

    However, changing the reading order comes with risks. Think about users using assistive technology. Make sure that they too experience your content the way you intend. This is one reason why dense is not the default.

    div#buttons {
      display: grid;
      grid-template-columns: auto auto auto auto;
      grid-template-rows: auto;
      grid-auto-flow: dense;
    
      button#one {
        grid-column: 1/2;
      }
      button#two {
        grid-column: 2/3;
      }
      button#three {
        grid-column: 4/5;
      }
      button#four {
        grid-column: 3/4;
        /* grid-area: 1/3/2/4; */
      }
    }
    <div id="buttons">
      <button id="one">One</button>
      <button id="two">Two</button>
      <button id="three">Three</button>
      <button id="four">Four</button>
    </div>