firefoxcss-gridsubgridfirefox-nightly

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


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;
  }


Solution

  • 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>