How to Flatten Nested Divs to Display Them in a CSS Grid

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>

How to skip nested object tags when using them to have key elements?

I avoided the creation of nested tags by building the html structure with within a string and then injecting that string within a div through dangerouslySetInnerHTML

That way I could preserve the css grid structure and not getting the warning

Is there a way to place a grand-child element on a CSS grids?

I think you are after CSS subgrid which is not supported as yet, it is in the CSS grid level 2 spec.

Here is a link explaining what it is and how it works. https://www.smashingmagazine.com/2018/07/css-grid-2/

Move elements outside the column in CSS grid

This is not something I came up with but it is what you are looking for I believe.
Add this .full-bleed class to the element with .additional-info class and it will span across the whole page.

It will take up the full width of the viewport and center it using transform and translate. Alternatively, you could use negative margins. It will escape any container, so even if your parent element is nested and not full width, this will be.

No need for CSS grid in this case.

// Escape any container, set this element to be 100vw and aligned to viewport without taking it out of normal document flow.
.full-bleed {
width: 100vw;
margin-left: 50%;
transform: translateX(-50%);
}

Equal height of elements inside grid item with CSS grid layout

Is it even possible?

tldr; Yes.

Codepen Demo #1

Codepen Demo # 2 (Uses SASS and is configurable)


The difficulty here is that each article is a grid within itself and therefore any one article has no knowledge about another. Because of this, there is no way for a component of one article like a header to adjust according to the height of a header in another article.

There is actually a way to pull this off with css grids & without changing any markup!

We could 'flatten' the structure with CSS such that all the components of all the articles are part of just one CSS grid - the article container.

This is possible without even changing the current markup by setting the articles with display: contents

display: contents (caniuse)

From Caniuse:

display: contents causes an element's children to appear as if they
were direct children of the element's parent, ignoring the element
itself. This can be useful when a wrapper element should be ignored
when using CSS grid or similar layout techniques.

So if we set the articles with display: contents

.container article {
display: contents;
}

Now all of the headers, sections and footer become (direct) grid items (of the container - which has display:grid) which we can arrange using the grid-template-areas property.

.container {
display: grid;
grid-column-gap: 1em; /* horizontal gap between articles */
grid-template-columns: repeat(3, 1fr);

grid-template-areas: "header1 header2 header3"
"section1 section2 section3"
"footer1 footer2 footer3"
"header4 header5 header6"
"section4 section5 section6"
"footer4 footer5 footer6"
}

Since each header/section/footer take up exactly one cell - this forces them to take up the same vertical height. So e.g. header1,header2 and header3 will all have the same height regardless of their content.

Now set the grid-area properties on each of the cells.

article:nth-child(1) header {
grid-area: header1;
}
article:nth-child(2) header {
grid-area: header2;
}
article:nth-child(3) header {
grid-area: header3;
}
article:nth-child(4) header {
grid-area: header4;
}
article:nth-child(1) section {
grid-area: section1;
}
...
article:nth-child(4) section {
grid-area: section4;
}
article:nth-child(1) footer {
grid-area: footer1;
}
...
article:nth-child(4) footer {
grid-area: footer4;
}

Finally, set a vertical gap between each row of articles (starting from the second row of articles):

article:nth-child(n + 4) header {
margin-top: 1em;
}

Demo:

body {  width: 100%;  max-width: 1024px;  margin: auto;}
.container { display: grid; grid-column-gap: 1em; grid-template-columns: repeat(3, 1fr); grid-template-areas: "header1 header2 header3" "section1 section2 section3" "footer1 footer2 footer3" "header4 header5 header6" "section4 section5 section6" "footer4 footer5 footer6"}
.container article { display: contents;}
article header { background-color: #eeeeee;}
article section { background-color: #cccccc;}
article footer { background-color: #dddddd;}
article:nth-child(n + 4) header { margin-top: 1em;}
article:nth-child(1) header { grid-area: header1;}article:nth-child(2) header { grid-area: header2;}article:nth-child(3) header { grid-area: header3;}article:nth-child(4) header { grid-area: header4;}article:nth-child(1) section { grid-area: section1;}article:nth-child(2) section { grid-area: section2;}article:nth-child(3) section { grid-area: section3;}article:nth-child(4) section { grid-area: section4;}article:nth-child(1) footer { grid-area: footer1;}article:nth-child(2) footer { grid-area: footer2;}article:nth-child(3) footer { grid-area: footer3;}article:nth-child(4) footer { grid-area: footer4;}
<div class="container">    <article>        <header>            <h2>Header</h2>            <h2>Header</h2>        </header>        <section>            <p>Content</p>        </section>        <footer>            <p>Footer</p>        </footer>    </article>    <article>        <header>            <h2>Header</h2>        </header>        <section>            <p>Content</p>            <p>Content</p>            <p>Content</p>            <p>Content</p>            <p>Content</p>        </section>        <footer>            <p>Footer</p>            <p>Footer</p>        </footer>    </article>    <article>        <header>            <h2>Header</h2>        </header>        <section>            <p>Content</p>            <p>Content</p>            <p>Content</p>        </section>        <footer>            <p>Footer</p>        </footer>    </article>    <article>        <header>            <h2>Header</h2>        </header>        <section>            <p>Content</p>            <p>Content</p>            <p>Content</p>            <p>Content</p>        </section>        <footer>            <p>Footer</p>            <p>Footer</p>        </footer>    </article></div>


Related Topics



Leave a reply



Submit