Conflict between CSS-flexbox and CSS-grid when nesting grids

Hello everyone! I was playing with CSS-grid when I got into this conflict.


<style>
.container > div{
  /*flex starts here*/
  display: flex;
  align-items: center;
  justify-content: center;
  /*flex ends here*/
  font-size: 30px;
  font-family: Consolas;
  padding: 10px;
  color: #000066;
  
}
.container{
  background: lightgray;
  
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 1fr 1fr 1fr 1fr;
  grid-template-areas:
  'x x m m'
  'x x c c'
  'x x c c'
  'x x f f';
}
.A{
  background: #cc66ff;
  grid-area: x;
  display: grid;
  grid-template-columns: auto;
  grid-template-rows: 100px 100px;
  
}
.son1{
  background: lightGreen;
}
.son2{
  background: paleTurquoise;
}
.B{
  background: #8533ff;
  grid-area: m;
  
}
.C{
  background: #3366ff;
  grid-area: c;
}
.D{
  background: #4da6ff;
  grid-area: f;
}
</style>

<div class='container'>
  <div class='A'>
     <div class='son1'>Son1</div>
     <div class='son2'>Son2</div>
  </div>
  <div class='B'>Menu</div>
  <div class='C'>Content</div>
  <div class='D'>Footer</div>
</div>

If i comment out the first three properties of the .container’s div, the code will partially work (the two children within A won’t completely stretch), but of course I won’t have the properties of the flex-box. How comes that only the two grandchildren of the container behave that way? How can I fix that? Thanks for your help!

1 Like

At the moment your code behaves the way it does because you’re setting display flex to all divs that are direct children of .container

.container > div

Because the only div with display flex that has children is the one with elements .son1 and .son2 it seems like that’s the only div that gets affected.

I’m not sure what’s the effect that you’re trying to achieve, so correct me if I’m wrong :slight_smile:

You want elements .son1 and .son2 to look like when you comment out this part of the code, and menu, content and footer to have display flex?

Yes this what I’d like to achieve…

All right, take a look at this codepen

I extracted setting up flex to separate class

.container > div  {
  font-size: 30px;
  font-family: Consolas;
  padding: 10px;
  color: #000066;
}

.flex {
  display: flex;
  align-items: center;
  justify-content: center;
}

And added this flex class only to these elements where you want it

  <div class='B flex'>Menu</div>
  <div class='C flex'>Content</div>
  <div class='D flex'>Footer</div>

I hope it’s something you’re looking for :wink:

1 Like

Wonderful buddy! So simple and yet so effective! I appreciate a lot your help :sweat_smile:

1 Like

Cool! I’m glad to help, happy coding :smiley:

(If you don’t mind a bonus question, is there any way to make the two grids fill the whole container?)

I’m sure there is a way, I just don’t know what you mean by that?

Container element and inside of it two elements with display set to grid?

Like in this example:

<style>
  .container {
    font-size: 1.5em;
    min-height: 300px;
    width: 100%;
    background: LightGray;
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto 1fr auto;
    
    grid-template-areas:
      "advert header"
      "advert content"
      "advert footer";
  }
  .item1 {
    background: LightSkyBlue;
    grid-area: header;
  }

  .item2 {
    background: LightSalmon;
    grid-area: advert;
  }

  .item3 {
    background: PaleTurquoise;
    grid-area: content;
    /* Only change code below this line */
    display: grid;
    grid-template-columns: 2fr 2fr;

    /* Only change code above this line */
  }

  .item4 {
    background: lightpink;
    grid-area: footer;
  }

  .itemOne {
    background: PaleGreen;
  }

  .itemTwo {
    background: BlanchedAlmond;
  }

</style>

<div class="container">
  <div class="item1">header</div>
  <div class="item2">advert</div>
  <div class="item3">
    <div class="itemOne">paragraph1</div>
    <div class="itemTwo">paragraph2</div>
  </div>
  <div class="item4">footer</div>
</div>


This is how this example looks like when I load it, what would you like to change here?
I don’t know what do you mean by filling the whole container, maybe you mean this white border around the container?
It’s the default margin that it set on body element, you can remove it like so:

body {
  margin: 0;
}

Capture
I’d like no margin within the .A grid, in other words I’d like the two grids (Son1 and Son2) within it to fill up all the space

Maybe all you really need is just one grid for all these elements something like

.container {  
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, 1fr);
  grid-template-areas:
  's1 s1 m m'
  's1 s1 c c'
  's2 s2 c c'
  's2 s2 f f';
}

.container > div {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
}
<div class='container'>
  <div class='son1'>Son1</div>
  <div class='son2'>Son2</div>
  <div class='menu'>Menu</div>
  <div class='content'>Content</div>
  <div class='footer'>Footer</div>
</div>

Well, yes, that’s surely an option, but what if later on I’ll want to fill up dynamically a grid (with JS for instance)? Let’s say, for example, that by default I have 4 grids, with their default colors/contents; what if I want to make possible for the user to fill up one of the grids with his images (a sort of upload thing); says, his profile picture and a random photo that rapresents him; if he uploads one, half of the parent is occupied; if two, all the content. An example :

<style>
  .container {
    background: lightgreen;
    width: 400px;
    height: 400px;
    display: grid;
    grid-template: 
    'childA' 50%
    'childB' 50%
    / 100%
  }
  button{
    background: gray;
    padding: 20px;
    font-size: 25px;
   
  }


</style>
<div class='container'>
  <div class='childA' id='A'></div>
  <div class='childB' id='B'></div>
  <button onClick="color()">Test me</button>
</div>
<script>
  
  function color(){
    document.getElementById('A').style = 'background: blue;'
  }
</script>

Do you mean grids or grid items? I’m confused to be honest.