Does "Subgrid" Need to Be Specified at Every Level in a Nested CSS Grid?

488 Views Asked by At

I've been trying out Firefox's implementation of the CSS subgrid spec in Nightly for an add-on, and have what I think is a really basic question that I couldn't find an explicit answer to on the MDN.

If I have a deeply nested element hierarchy, and only want to lay out its terminal nodes (the ones deepest in the hierarchy) on a single grid defined at the top-level element, do I have to make sure grid-template-columns/grid-template-rows is set to "subgrid" for every level inbetween + make sure that they've got grid-column/grid-row set to span the ancestor's entire grid?

In my example below I initially made everything with div's, but then when I introduced the semantics I found myself needing to specify "subgrid that should span its entire parent's grid" over and over in the middle layers, to the point where I just added a single selector to set that by default for every element. (The code below also exists in this fiddle). If I were to start from scratch I think I'd only set grid-column/grid-row specifically for the terminal nodes instead, which led to the question.

<ol class="root">
  <li class="topOfPage">
    <button>
      Read to Top of Page
    </button>
   </li>
   <li class="middleOfPage">
     <ol>
       <li class="topLine">
         <button>
           Read Previous Line
         </button>
       </li>
       <li class="middleLineContent">
         <ul>
           <li class="middleLine">
             <button>
               Read Current Line
              </button>
           </li>
           <li class="lineContent">
             <ol>
               <li class="prevWord">
                 <button>
                   Read Previous Word
                 </button>
               </li>
               <li class="middleWordContent">
               <ul>
                 <li class="middleWord">
                   <button>
                     Read Current Word
                   </button>
                 </li>
                 <li class="charContent">
                   <ol>
                     <li class="prevChar">
                       <button>
                         Read Previous Character
                        </button>
                     </li>
                     <li class="middleChar">
                       <button>
                         Read Current Character
                       </button>
                     </li>
                     <li class="nextChar">
                       <button>
                         Read Next Character
                       </button>
                     </li>
                   </ol>
                 </li>
               </ul>
             </li>
             <li class="nextWord">
               <button>
                 Read Next Word
               </button>
             </li>
           </ol>
         </li>
       </ul>
     </li>
     <li class="bottomLine">
       <button>
         Read Next Line
       </button>
     </li>
   </ol>
 </li>
 <li class="bottomOfPage">
   <button>
     Read to Bottom of Page
   </button>
 </li>
 </ol>
li {
  list-style-type: none;
}

ol,ul {
  padding-left: 0;
}

.root {
    display: grid;
    grid-template-columns: repeat(5, auto);
    grid-template-rows: repeat(5, auto);

    height: 250px;
}

.root * {
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    grid-column: 1/-1;
    grid-row: 1/-1;
}

  .root .topOfPage {
    grid-column: 1 / 6;
    grid-row: 1 / 1;
  }

  .root .bottomOfPage {
    grid-column: 1 / 6;
    grid-row: 5 / 5;
  }

  .root .middleOfPage {
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    grid-column: 1 / 6;
    grid-row: 2 / 6;
  }

  .root .middleOfPage .topLine {
    grid-column: 1 / 6;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .bottomLine {
    grid-column: 1 / 6;
    grid-row: 3 / 3;
  }

  .root .middleOfPage .middleLineContent {
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    grid-column: 1 / 6;
    grid-row: 2 / 2;
  }

  .root .middleOfPage .middleLineContent .middleLine {
    grid-column: 1 / 6;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent {
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    grid-column: 1 / 6;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent .prevWord {
    grid-column: 1 / 1;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent .nextWord {
    grid-column: 6 / 6;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent .middleWordContent {
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    grid-column: 2 / 5;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent .middleWordContent .middleWord {
    grid-column: 1 / 4;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent .middleWordContent .charContent {
    display: grid;
    grid-template-columns: subgrid;
    grid-template-rows: subgrid;
    grid-column: 1 / 4;
    grid-row: 1 / 1;
  }

  .root .middleOfPage .middleLineContent .lineContent .middleWordContent .charContent .prevChar {
    grid-column: 1 / 1;
    grid-row: 1 / 1;

    width: 75px;
  }

  .root .middleOfPage .middleLineContent .lineContent .middleWordContent .charContent .middleChar {
    grid-column: 2 / 2;
    grid-row: 1 / 1;

    width: 75px;
  }

  .root .middleOfPage .middleLineContent .lineContent .middleWordContent .charContent .nextChar {
    grid-column: 3 / 3;
    grid-row: 1 / 1;

    width: 75px;
  }

1

There are 1 best solutions below

0
Mendel Gordon On

Yes, based on my testing, it needs to be specified at every level, but you can set it to "inherit", instead of needing to add the correct values for each level:

<div style="display: grid">
  <div style="grid-column: 1; grid-row: 1">Nav (Row 1)</div>
  <div style="grid-column: 1; grid-row: 1/99; grid-template-rows: subgrid; display: inherit">
    <div style="display: inherit; grid-column: inherit; grid-row: inherit; grid-template-rows: inherit">
      <div style="display: inherit; grid-column: inherit; grid-row: inherit; grid-template-rows: inherit">
        <div style="grid-row: 1; justify-self: center">Hero (Row 1, centered)</div>
        <div style="grid-row: 2">Row 2</div>
        <div>Row 3</div>
      </div>
    </div>
  </div>
</div>