Move grandchildren elements in CSS grid-template-areas items around
Asked Answered
C

2

8

I'm trying to learn about grid-template-areas.

But my code is not working like the intended area template:

"title title"
"both-a both-b"
"left-a right-a"
"left-b right-b"

All left items should be to the left of the corresponding ("a" or "b") right items.

* {
  border: 1px solid black;
}

.wrapper {
  display: grid;
  grid-template-areas: "title title"
                       "both-a both-b"                       
                       "left-a right-a"
                       "left-b right-b";
}

.wrapper > header {
  grid-area: title;
}

.both > .topic-a {
  grid-area: both-a;  
}

.both > .topic-b {
  grid-area: both-b;  
}

.left > .topic-a {
  grid-area: left-a;
}

.left > .topic-b {
  grid-area: left-b;
}

.right > .topic-a {
  grid-area: right-a;
}

.right > .topic-b {
  grid-area: right-b;
}


.left-side {
  color: red;
}

.right-side {
  color: blue;
}
<article class="wrapper">
<header><h1>Title</h1></header>

<section class="both">
<section class="topic-a">
<ol>
<li>both-A 1st item</li>
<li>2nd item</li>
<li>3rd item</li>
</ol>
</section>
<section class="topic-b">
<ol>
<li>both-B 1st item</li>
<li>2nd item</li>
<li>3rd item</li>
</ol>
</section>
</section>

<section class="left-side">
<section class="topic-a">
<ol>
<li>left-A 1st item</li>
<li>2nd item</li>
<li>3rd item</li>
<li>nth item</li>
<li>nth item</li>
<li>nth item</li>
<li>nth item</li>
<li>nth item</li>
</ol>
</section>
<section class="topic-b">
<ol>
<li>left-B 1st item</li>
<li>2nd item</li>
<li>3rd item</li>
</ol>
</section>
</section>

<section class="right-side">
<section class="topic-a">
<ol>
<li>right-A 1st item</li>
<li>2nd item</li>
<li>3rd item</li>
</ol>
</section>
<section class="topic-b">
<ol>
<li>right-B 1st item</li>
<li>2nd item</li>
<li>3rd item</li>
<li>nth item</li>
<li>nth item</li>
<li>nth item</li>
<li>nth item</li>
<li>nth item</li>
</ol>
</section>
</section>

</article>

I know it's probably a silly mistake, but I can't figure it out.

Centroid answered 25/12, 2017 at 8:9 Comment(5)
grid is only working on a parent-child relationship. You are giving grid-area style to grand-children of the grid, this won't work.Zavala
@Zavala Ah, I see! Thanks for the heads-up! Should I nest grids then? Or maybe flexboxes? Although, the problem remains, these are children of different sections... maybe I should just delete the parents and make them children instead of grandchildrenCentroid
Well, the decision is yours ... But probably you should nest flexboxes inside the grid, given the layout that I can seeZavala
@Zavala But is it possible to have grandchildren as flex-items? I'm trying without success to make a flexboxCentroid
Finally I found this: "... container's display property to flex or inline-flex. As soon as we do this the direct children of that container become flex items. " developer.mozilla.org/en-US/docs/Web/CSS/… . So I don't think a flexbox is possible, there's no common parent for left-side and right-side, to make left-a be on the left side of right-aCentroid
C
4

Alright, maybe this will help someone.

It's not possible to do what I want, because both CSS flexbox and grid only have direct children as items (so grandchildren are not possible items).

Therefore, I had to exclude two sections and put both left-ab and right-ab under a same parent. This way, I can have left-a next to right-a, and left-b next to right-b.

This is the resulting code:
(my CSS skills are very poor, corrections would be very welcome!)

* {
  border: 1px black solid;
}

.wrapper {
  display: grid;
  grid-template-areas: "title" "both" "left-right";
}

.wrapper>header {
  grid-area: title;
}

.both {
  grid-area: both;
  display: flex;
  flex-flow: row nowrap;
  align-items: stretch;
}

.both>* {
  flex: 1;
}

.left-right {
  display: flex;
  flex-flow: row wrap;
  align-items: stretch;
}

.left-right>* {
  flex: 1;
  min-width: 40%;
}

.both>.topic-a {
  order: 1;
}

.both>.topic-b {
  order: 2;
}

.topic-a.left-side {
  order: 3;
}

.topic-b.left-side {
  order: 5;
}

.topic-a.right-side {
  order: 4;
}

.topic-b.right-side {
  order: 6;
}

.left-side {
  color: red;
  background-color: #FCC;
}

.right-side {
  color: blue;
  background-color: lightblue;
}
<article class="wrapper">
  <header>
    <h1>Title</h1>
  </header>

  <section class="both">
    <section class="topic-a">
      <ol>
        <li>both-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
    <section class="topic-b">
      <ol>
        <li>both-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
  </section>

  <div class="left-right">


    <section class="topic-a left-side">
      <ol>
        <li>left-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
      </ol>
    </section>
    <section class="topic-b left-side">
      <ol>
        <li>left-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>



    <section class="topic-a right-side">
      <ol>
        <li>right-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
    <section class="topic-b right-side">
      <ol>
        <li>right-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
      </ol>
    </section>


  </div>

</article>
Centroid answered 25/12, 2017 at 11:59 Comment(0)
P
12

You can bypass child (2nd level) elements by using display: contents; in it. Thus grandchild (3rd level) elelments will be affected from the parent (1st level) grid.

* {
  border: 1px solid black;
}

.wrapper {
  display: grid;
  grid-template-areas: "title title" "both-a both-b" "left-a right-a" "left-b right-b";
}

.both,
.left-side,
.right-side {
  display: contents; /* Bypass direct Child */
}

.wrapper>header {
  grid-area: title;
}

.both>.topic-a {
  grid-area: both-a;
}

.both>.topic-b {
  grid-area: both-b;
}

.left>.topic-a {
  grid-area: left-a;
}

.left-side>.topic-b {
  grid-area: left-b;
}

.right-side>.topic-a {
  grid-area: right-a;
}

.right-side>.topic-b {
  grid-area: right-b;
}

.left-side {
  color: red;
}

.right-side {
  color: blue;
}
<article class="wrapper">
  <header>
    <h1>Title</h1>
  </header>

  <section class="both">
    <section class="topic-a">
      <ol>
        <li>both-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
    <section class="topic-b">
      <ol>
        <li>both-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
  </section>

  <section class="left-side">
    <section class="topic-a">
      <ol>
        <li>left-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
      </ol>
    </section>
    <section class="topic-b">
      <ol>
        <li>left-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
  </section>

  <section class="right-side">
    <section class="topic-a">
      <ol>
        <li>right-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
    <section class="topic-b">
      <ol>
        <li>right-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
      </ol>
    </section>
  </section>

</article>
Photoengraving answered 2/4, 2022 at 9:19 Comment(3)
Thanks for pointing this out! The only possible issue with display: contents is that if you, for example, used background-color instead of color or added border rules to the classes with display: content it wouldn't work (you can, of course, use a different selector, like .left-side li {background: orange;})Centroid
I thought this was too good to be true. This gives so much flexibility.Additament
For some reason, this seems to break grid-template-rows: repeat(auto-fit, <len>) in every browser I've tried.Additament
C
4

Alright, maybe this will help someone.

It's not possible to do what I want, because both CSS flexbox and grid only have direct children as items (so grandchildren are not possible items).

Therefore, I had to exclude two sections and put both left-ab and right-ab under a same parent. This way, I can have left-a next to right-a, and left-b next to right-b.

This is the resulting code:
(my CSS skills are very poor, corrections would be very welcome!)

* {
  border: 1px black solid;
}

.wrapper {
  display: grid;
  grid-template-areas: "title" "both" "left-right";
}

.wrapper>header {
  grid-area: title;
}

.both {
  grid-area: both;
  display: flex;
  flex-flow: row nowrap;
  align-items: stretch;
}

.both>* {
  flex: 1;
}

.left-right {
  display: flex;
  flex-flow: row wrap;
  align-items: stretch;
}

.left-right>* {
  flex: 1;
  min-width: 40%;
}

.both>.topic-a {
  order: 1;
}

.both>.topic-b {
  order: 2;
}

.topic-a.left-side {
  order: 3;
}

.topic-b.left-side {
  order: 5;
}

.topic-a.right-side {
  order: 4;
}

.topic-b.right-side {
  order: 6;
}

.left-side {
  color: red;
  background-color: #FCC;
}

.right-side {
  color: blue;
  background-color: lightblue;
}
<article class="wrapper">
  <header>
    <h1>Title</h1>
  </header>

  <section class="both">
    <section class="topic-a">
      <ol>
        <li>both-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
    <section class="topic-b">
      <ol>
        <li>both-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
  </section>

  <div class="left-right">


    <section class="topic-a left-side">
      <ol>
        <li>left-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
      </ol>
    </section>
    <section class="topic-b left-side">
      <ol>
        <li>left-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>



    <section class="topic-a right-side">
      <ol>
        <li>right-A 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
      </ol>
    </section>
    <section class="topic-b right-side">
      <ol>
        <li>right-B 1st item</li>
        <li>2nd item</li>
        <li>3rd item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
        <li>nth item</li>
      </ol>
    </section>


  </div>

</article>
Centroid answered 25/12, 2017 at 11:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.