skip to Main Content

tl;dr is there a way to align rows of a list of column objects in CSS?

I have a bunch of objects with properties that I want to show as separate elements on the page, however I want their properties to align together like a table.
A picture is worth a thousand words:

enter image description here

All the cells should align vertically, however the objects are defined as columns rather than rows.

Is there a way to achieve this with HTML/CSS?

The only way I could think of so far is to split the data, so the first property of all objects is defined in a row of cells, and the second property would be the second row, etc., with some padding between the columns. However that requires very messy code (JSX in this case) to populate the cells, such as a loop per property, and I am not sure if it can handle wrapping on overflow and such like modern grids/flexboxes can.

2

Answers


  1. As per my commment above, subgrid would be ideal for this because, quite often, you wrap these comments in divs. However if you’re prepared to forgo wrapper divs you can replicate this just using grid itself by using grid-template-rows to control the height and using grid-auto-flow to set up a column-based layout. See an example of the code below.

    See CSS tricks for a good primer on grid and this video from Kevin Powell. Also this video for subgrid.

    .container {
      display: grid;
      column-gap: 1rem;
      
      /* fill by columns, not rows (which is the default */
      grid-auto-flow: column; 
      
      /* set up each row so that it fits the content but the bottom one has to be at least 100px so it looks like your example*/
      grid-template-rows: max-content max-content minmax(100px, max-content); 
      
      /* equally space each column */
      grid-auto-columns: 1fr; 
    }
    
    
    /* the CSS below is just prettification, not really relevant to the problem you're having */
    .container > div {
      padding: 0.25rem;
    }
    
    .header {
      border: 2px solid black;
      border-bottom-color: red;
    }
    
    .body {
      border: 2px solid black;
      border-top: none;
      border-bottom-color:red;
    }
    
    .footer {
      border: 2px solid black;
      border-top: none;
    }
    <div class="container">
      <div class="header">Some Text</div>
      <div class="body">Some other<br>text</div>
      <div class="footer"></div>
    
      <div class="header">Some longer text</div>
      <div class="body"></div>
      <div class="footer">Some other comment</div>
    
      <div class="header"></div>
      <div class="body"></div>
      <div class="footer"></div>
    </div>

    Edited to add

    For any number of rows, use CSS custom properties and set that property in the style attribute of the parent wrapper

    .container {
      display: grid;
      column-gap: 1rem;
      
      /* fill by columns, not rows (which is the default */
      grid-auto-flow: column; 
      
      /* set up each row so that it fits the content but the bottom one has to be at least 100px so it looks like your example*/
      grid-template-rows: repeat(var(--num-rows), max-content); 
      
      /* equally space each column */
      grid-auto-columns: 1fr; 
    }
    
    
    /* the CSS below is just prettification, not really relevant to the problem you're having */
    .container > div {
      padding: 0.25rem;
    }
    
    .header {
      border: 2px solid black;
      border-bottom-color: red;
    }
    
    .body, .extra-body {
      border: 2px solid black;
      border-top: none;
      border-bottom-color:red;
    }
    
    .footer {
      border: 2px solid black;
      border-top: none;
    }
    <div class="container" style='--num-rows:3;'><!-- you can use JS to drop the number of rows here -->
      <div class="header">Some Text</div>
      <div class="body">Some other<br>text</div>
      <div class="footer"></div>
    
      <div class="header">Some longer text</div>
      <div class="body"></div>
      <div class="footer">Some other comment</div>
    
      <div class="header"></div>
      <div class="body"></div>
      <div class="footer"></div>
    </div>
    
    <p>4 row example</p>
    <div class="container" style='--num-rows:4;'><!-- you can use JS to drop the number of rows here -->
      <div class="header">Some Text</div>
      <div class="body">Some other<br>text</div>
      <div class='extra-body'>here</div>
      <div class="footer"></div>
    
      <div class="header">Some longer text</div>
      <div class="body"></div>
      <div class='extra-body'></div>
      <div class="footer">Some other comment</div>
    
      <div class="header"></div>
      <div class="body"></div>
      <div class='extra-body'>here</div>
      <div class="footer"></div>
    </div>
    Login or Signup to reply.
  2. display: contents helps here, but check on caniuse.com that some feature you want in your real life example is properly implemented.

    Here’s a simple 3 column (=3 ‘object’) example:

    .objects {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 20px;
    }
    
    .objects>* {
      display: contents;
    }
    
    .objects>*>* {
      border: solid red 1px;
    }
    
    .objects>div>div:nth-child(2) {
      grid-row: 2;
    }
    
    .objects>div>div:nth-child(3) {
      grid-row: 3;
    }
    <div class="objects">
      <div>
        <div>1<br>1</div>
        <div>1</div>
        <div>1</div>
      </div>
      <div>
        <div>2</div>
        <div>2<br>2</div>
        <div>2</div>
      </div>
      <div>
        <div>3</div>
        <div>3</div>
        <div>3</div>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search