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-*
andgrid-*-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:
- a clean and semantically-meaningful element,
- an HTML structure that falls within the scope of Grid's parent-child relationship, and
- with one nested grid, that occupies the same space as the parent grid, you can align your items along grid lines.
body { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-areas: " nav nav nav " " . content . "}
nav { grid-area: nav; display: grid; grid-template-columns: repeat(3, 1fr); background-color: lightblue;}
main { grid-area: content;}
<nav> <a>item 1</a> <a>item 2</a> <a>item 3</a></nav>
<main> <h1>content</h1></main>
Related Topics
What Is the Way to Add Horizontal Scroll on Material-Ui Table With Many Columns
Center Content in Responsive Bootstrap Navbar
Equal Height Rows in CSS Grid Layout
Css '≫' Selector; What Is It
Any Way to Declare a Size/Partial Border to a Box
Why Does the Order of Media Queries Matter in Css
How to Conditionally Apply a Class
Css - Why Doesn't Percentage Height Work
How to Show Only Corner Borders
Responsive CSS Background Images
How to Select the "Last Child" With a Specific Class Name in Css
Css Force Image Resize and Keep Aspect Ratio
Difference Between "Word-Break: Break-All" Versus "Word-Wrap: Break-Word" in Css
Change Bootstrap Navbar Collapse Breakpoint Without Using Less
Css Reset - What Exactly Does It Do
Css 100% Height With Padding/Margin