Search code examples
cssflexboxgrid-layout

Laying out elements in varying height in three columns in CSS


I would like to lay out some elements in CSS which "flow" vertically in three or four columns, which would look like this :

enter image description here

The layout should put elements in the columns as evenly as possible.

A normal grid layout wouldn't work because of the vertical grid lines, and flexbox doesn't seem to offer anything with its column flow direction.

Does anyone have an idea for a good approach to laying out elements like this?


Solution

  • The answer depends on the sequence you want the elements to be displayed.

    If you’re happy for the sequence to be column 1 top to bottom, followed by column 2 top to bottom, followed by column 3 top to bottom, then you can use CSS’s often-overlooked multi-column layout. Just style the wrapper with columns: 3.

    let s = ''
    for (let i = 0; i < 20; i++) {
      const hue = Math.floor(Math.random() * 256)
      const height = Math.floor(Math.random() * 100) + 25
      s += `<div style="border-color: hsl(${hue}, 100%, 50%); background-color: hsl(${hue}, 50%, 97%); height: ${height}px;">${i + 1}</div>`
    }
    document.querySelector('body').innerHTML = s
    body {
      margin: 1em;
      columns: 3;
      font-family: monospace;
      font-size: 18px;
    }
    
    div {
      border: 5px solid black;
      margin-bottom: 1em;
      break-inside: avoid;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    If instead you want the first three elements to be displayed at the top of columns 1, 2 and 3, and then element 4 to be displayed in whichever column is the shortest, then that’s a masonry layout. Direct support for this in CSS is being worked on, but in the meantime there are various techniques you can try.