skip to Main Content

I want to create an arbitrary n x n matrix using CSS Grid. My HTML structure is:

    <div class="matrix">
        <div class="matrix-corner"></div>
        <div class="matrix-header-row">Header1</div>
        <div class="matrix-header-row">Header2</div>
        <div class="matrix-header-col">Header1</div>
        <div class="matrix-header-col">Header2</div>
        <div class="matrix-row">      
            <div class="matrix-cell">100%</div>     
            <div class="matrix-cell">50%</div>     
        </div>
        <div class="matrix-row">
            <div class="matrix-cell">50%</div>
            <div class="matrix-cell">100%</div>
        </div>
    </div>

Where the size of the matrix will ultimately be arbitrary (i.e. I can’t fix the number of columns in the grid CSS).

I can easily force the row and column headers to be in their respective places using grid-row: 1/2 and grid-column: 1/2 respectively – however I’m having difficulty fixing the matrix-row elements so that they stack one ontop of another; when I use grid-column: 2/-1 Chrome ignores the -1 (since it doesn’t relate to an explicit grid column?).

Here’s my full CSS:

    .matrix {        
        display: grid;
        grid-auto-flow: dense;        
    }

    .matrix-corner {
        grid-row: 1/2;
        grid-column: 1/2;
    }

    .matrix-header-row {
        grid-row: 1/2;
        
    }

    .matrix-header-col {
        grid-column: 1/2;
    }

    .matrix-row {
        grid-column: 2 / -1;
        display: grid;
        grid-template-columns: subgrid;
        border: 1px solid red;
    }

What I want

What I’ve got

2

Answers


  1. Need to wrap each row in a matrix-row container, but each matrix-cell must be directly placed within the grid to ensure proper alignment.

    .matrix {
        display: grid;
        grid-template-columns: auto repeat(2, 1fr); /* Adjust the number of columns as needed */
        grid-template-rows: auto repeat(2, auto);  /* Adjust the number of rows as needed */
        gap: 10px;
    }
    
    .matrix-corner {
        grid-row: 1 / 2;
        grid-column: 1 / 2;
    }
    
    .matrix-header-row:nth-child(2) {
        grid-row: 1 / 2;
        grid-column: 2 / 3;
    }
    
    .matrix-header-row:nth-child(3) {
        grid-row: 1 / 2;
        grid-column: 3 / 4;
    }
    
    .matrix-header-col:nth-child(4) {
        grid-column: 1 / 2;
        grid-row: 2 / 3;
    }
    
    .matrix-header-col:nth-child(5) {
        grid-column: 1 / 2;
        grid-row: 3 / 4;
    }
    
    .matrix-cell:nth-child(6) {
        grid-column: 2 / 3;
        grid-row: 2 / 3;
    }
    
    .matrix-cell:nth-child(7) {
        grid-column: 3 / 4;
        grid-row: 2 / 3;
    }
    
    .matrix-cell:nth-child(8) {
        grid-column: 2 / 3;
        grid-row: 3 / 4;
    }
    
    .matrix-cell:nth-child(9) {
        grid-column: 3 / 4;
        grid-row: 3 / 4;
    }
    
    .matrix-cell {
        border: 1px solid red;
        padding: 10px;
        text-align: center;
    }
    <div class="matrix">
        <div class="matrix-corner"></div>
        <div class="matrix-header-row">Header1</div>
        <div class="matrix-header-row">Header2</div>
        <div class="matrix-header-col">Header1</div>
        <div class="matrix-header-col">Header2</div>
        
        <div class="matrix-cell">100%</div>     
        <div class="matrix-cell">50%</div>
        <div class="matrix-cell">50%</div>
        <div class="matrix-cell">100%</div>
    </div>
    Login or Signup to reply.
  2. A table would probably be the proper element for this but you have selected CSS-Grid.

    As such, it would be appropriate to wrap "row title" in with the row contents.

    Equally, wrapping the column headers in their own row make sense too.

    Then we can leverage auto-fit (or auto-fill) and subgrid.

    Then we only need to specify where rows start and end.

    This permits us to dispose of the spacer div

    .matrix {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
      grid-auto-flow: row;
      gap: .25em;
      margin-bottom: 1em;
    }
    
    .matrix-column {
      display: grid;
      grid-template-columns: subgrid;
      grid-column-start: 2;
      grid-column-end: -1;
    }
    
    .matrix-row {
      display: grid;
      grid-template-columns: subgrid;
      grid-column-start: 1;
      grid-column-end: -1;
    }
    
    .matrix-header-col,
    .matrix-header-row,
    .matrix-cell {
      border: 1px solid grey;
    }
    <div class="matrix">
    
      <div class="matrix-column">
        <div class="matrix-header-col">Column 1</div>
        <div class="matrix-header-col">Column 2</div>
      </div>
      <div class="matrix-row">
        <div class="matrix-header-row">Row 1</div>
        <div class="matrix-cell">100%</div>
        <div class="matrix-cell">50%</div>
      </div>
      <div class="matrix-row">
        <div class="matrix-header-row">Row 2</div>
        <div class="matrix-cell">50%</div>
        <div class="matrix-cell">100%</div>
      </div>
    </div>
    
    <div class="matrix">
    
      <div class="matrix-column">
        <div class="matrix-header-col">Column 1</div>
        <div class="matrix-header-col">Column 2</div>
        <div class="matrix-header-col">Column 3</div>
      </div>
      <div class="matrix-row">
        <div class="matrix-header-row">Row 1</div>
        <div class="matrix-cell">100%</div>
        <div class="matrix-cell">50%</div>
        <div class="matrix-cell">75%</div>
      </div>
      <div class="matrix-row">
        <div class="matrix-header-row">Row 2</div>
        <div class="matrix-cell">50%</div>
        <div class="matrix-cell">100%</div>
        <div class="matrix-cell">75%</div>
      </div>
      <div class="matrix-row">
        <div class="matrix-header-row">Row 3</div>
        <div class="matrix-cell">75%</div>
        <div class="matrix-cell">75%</div>
        <div class="matrix-cell">75%</div>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search