Position Deeply Nested Elements in a Higher Level Grid Container

Position deeply nested elements in a higher level grid container

display: subgrid

From the CSS Grid Level 2 draft spec:

2. Grid Containers

Subgrids provide the ability to pass grid parameters down through nested elements, and content-based sizing information back up to their parent grid.

If the element is a grid item (i.e. it is in-flow and its parent is a
grid container), display: subgrid makes the element a subgrid (which is a
special type of grid container box) and consequently ignores its
grid-template-* and grid-*-gap properties in favor of adopting the
parent grid tracks that it spans.

3. Subgrids

A grid item can itself be a grid container by giving it display: grid. In this case the layout of its contents will be independent of the layout of the grid it participates in.

In some cases it might be necessary for the contents of multiple grid items to align to each other. A grid container that is itself a grid item can defer the definition of its rows and columns to its parent grid container by using display: subgrid, making it a subgrid.

In this case, the grid items of the subgrid participate in sizing the grid of the parent grid container, allowing the contents of both grids to align. Read more.

This feature has not yet been implemented in major browsers. Who knows when it will be.

In Grid, only the in-flow children of the container become grid items and can accept grid properties.

With display: subgrid on a grid item, the children of the item respect the lines of the container.

According to the Grid Level 1 spec, display: subgrid has been deferred to Level 2.

For now, display: grid on grid items (i.e., nested grid containers) may be useful in some cases.

Another possible workaround is display: contents. The method is explained here:

  • What is an alternative to css subgrid?

More information:

  • https://blogs.igalia.com/mrego/2016/02/12/subgrids-thinking-out-loud/
  • https://bugzilla.mozilla.org/show_bug.cgi?id=1240834

CSS grid nested elements

If it's okay to use display: contents for the form, it's possible.

.grid {
display: grid;
}

form {
display: contents;
}

.item1 {
grid-row: 1
}

.nest {
grid-row: 2
}

.item2 {
grid-row: 3
}
<div class="grid">
<div class="nest">Item i want to nested</div>
<form>
<div class="item1">Item 1</div>
<div class="item2"> Item 2</div>
</form>
</div>

css grid with nested div structure

Nested grids are possible, but make sure that the parent of the innermost divs does itself have display:grid. If you don't,

As these items are not direct children of the grid they do not participate in grid layout and so display in a normal document flow.

(from MDN: Basic concepts of grid layout.)

So all you need to do is assign those styles to the parent of the left and right divs.

.wrapper {  display: grid;  grid-template-columns: repeat(3, 1fr);  grid-gap: 10px;  grid-template-rows: 1;}
.cent { grid-column: 2; grid-row: 1;}
.cent + div { /* this works for now, but you should choose a better selector for this one */ display: grid; grid-column: 1 / 4; grid-row: 1;}
.left { grid-column: 1; grid-row: 1;}
.right { grid-column: 3; grid-row: 1;}
<div class="wrapper">  <div class="cent">center</div>  <div>    <!-- in reality there would be more divs and rows, I already have problems with one -->    <div class="left">left</div>    <div class="right">right</div>  </div></div>

How to flatten nested divs to display them in a CSS grid?

Grid properties aren't applying to your content divs because these divs are out-of-scope.

Grid formatting is limited to the parent-child relationship. This means that a grid container is always the parent and a grid item is always the child. Descendants of a grid container beyond the children are not part of grid layout and will not accept grid properties.

Because your content divs are two levels down from the grid container (#table), making them grandchildren not children, they are not grid items and will not accept grid properties.

More details: Grid properties not working on elements inside grid container


There are exceptions to the rule above, but they don't have much or any browser support.

display: contents is covered in another answer to this post. It enables an element to be ignored as a containing block by the parent, so the parent will recognize its grandchildren as normal children. But for now this method is effectively useless for production purposes, as it has weak browser support.

The more appropriate solution in this case would be display: subgrid, which enables the descendants of a grid container beyond the children (i.e., the children of grid items) to respect the lines of the container. But this feature has no browser support.

More details: Positioning content of grid items in primary container (subgrid feature)


If you want a pure CSS solution, maybe a combination of grid and flex can help.

Here's a general concept. No changes to the HTML.

#table {  display: grid;  grid-template-columns: 1fr;}
#table > div { display: flex;}
#table > div > div { flex: 1;}
<div id="table">  <div>    <div>      this is something long on the first row    </div>    <div>      short 1st row    </div>  </div>  <div>    <div>      wazaa 2nd row    </div>    <div>      wazii 2nd row    </div>  </div></div>

Align child elements at inner grid lines

Notice how your main element, an HTML5 semantically-meaningful container, eliminates the need for a div container, which was common prior to HTML5.

<!-- valid and efficient structure -->
<main>
<h1>content</h1>
</main>

<!-- valid but inefficient structure -->
<main>
<div>
<h1>content</h1>
</div>
</main>

Why aren't you applying this same principle to your navigation bar?

With the HTML5 nav tag available, why use list items?

Instead of this:

<nav>
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</nav>

Just do this:

<nav>
<a>item 1</a>
<a>item 2</a>
</nav>

This offers you at least three benefits:

  1. a clean and semantically-meaningful element,
  2. an HTML structure that falls within the scope of Grid's parent-child relationship, and
  3. with one nested grid, that occupies the same space as the parent grid, you can align your items along grid lines.