Creating 2x2 flex grid with different widths which stack

Viewed 84

I have been wrestling with flex and how to do a simple grid, with different widths, and then to make them stackable in mobile.

-------------------
menu  | A1     | B1
      | A2     | B2
--------------------

But then, when responsive, stacks to:

------------
    A1
------------
    B1
------------
    A2
------------
    B2

(the menu becomes a burger already)

So far I have:

.flex-row {
   display: flex;
   flex: 1;
   flex-direction: row;
   flex-wrap: wrap;
}

.flex-col {
   margin: 6px;
   padding: 0px;
   background-color: black;
   display: flex;
   justify-content: center;
   flex: 1;
   flex-direction: column;
   color: white;
}
<div class="container">
 <div class="sidebar-menu-col">
    menu here
 </div>
 <div class="flex-col">
   <div class="flex-col">A1</div>
   <div class="flex-col">B1</div>
   <div class="flex-col">A2</div>
   <div class="flex-col">B2</div>
 </div>
</div>

For some reason, I cannot get the width to work even when using something like flex: 0 0 15em;. In desktop, then things don't look good, and all show up as cols. Wondering how to break it so it's 2x2 on desktop (aside from the menu) and stacked in mobile.

2 Answers

you should be using grid instead for this. i have added display grid giving it 2 colums and 2 rows and in media querie for small devices it changes to 1 column and 4 rows..and i dnt understand the class you are targeting in css (.flex-row) as there are no html of that class..? and you shouldnt use same names for parent container and the childrens..

.container {
                display: flex;
                align-items: center;
                flex-wrap: wrap;
            }

            /* .flex-row {
                display: flex;
                flex: 1;
                flex-direction: row;
                flex-wrap: wrap;
            } */
            

            .flex-col-container {
                margin: 6px;
                padding: 0px;
                background-color: black;
                color: white;
                /* display: flex;
                justify-content: center; */
                display: grid;
                
                grid-auto-flow: row;
                grid-template-columns: 15em  5em; /*A1 and a2 is 15em & b1 and b2 is 5em*/
                grid-row: 2em 2em;/*2 rows with height of 2em*/
               

            }

            @media only screen and (max-width: 650px) {
                .flex-col-container {
                    grid-template-columns: 15em;/*1 column with width of 15em*/
                    grid-row: 2em 2em 2em 2em;/*4 rows with height of 2em*/

                }

            }
<div class="container">
        <div class="sidebar-menu-col">
            menu here
        </div>
        <div class="flex-col-container">
            <div class="flex-col">A1</div>
            <div class="flex-col">B1</div>
            <div class="flex-col">A2</div>
            <div class="flex-col">B2</div>
        </div>

Try this solution with flex and css-variables. Firstly, I renamed parent the element of the columns for better usability. Then we create three values for margins, width A and width B. With the:nth-of-type pseudo-class and odd, even arguments we assign the width. The last step, we create a breakpoint (@media) for mobile devices and edit the values A, B.

Flextbox solution

.container {
  display: flex;
}

.sidebar-menu-col {
  flex: 1 0 auto;
}

.wrapper {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
}

.flex-col {
  --margin: 6px;
  --A: 70%;
  --B: 30%;
  margin: var(--margin);
  padding: 0px;
  background-color: black;
  display: flex;
  justify-content: center;
  flex: 1;
  color: white;
}

.flex-col:nth-of-type(odd) {
  flex: 1 0 calc(var(--A) - var(--margin) * 2);
}

.flex-col:nth-of-type(even) {
  flex: 0 1 calc(var(--B) - var(--margin) * 2);
}

@media screen and (max-width: 560px) {
 .container {
    flex-flow: column;
  }
  .flex-col {
    --margin: 0px;
    --A: 100%;
    --B: 100%;
  }
}
<div class="container">
  <div class="sidebar-menu-col">menu here</div>
  <div class="wrapper">
    <div class="flex-col">A1</div>
    <div class="flex-col">B1</div>
    <div class="flex-col">A2</div>
    <div class="flex-col">B2</div>
  </div>
</div>

Grid solution

.container {
  display: flex;
}

.sidebar-menu-col {
  flex: 1 0 auto;
}

.wrapper {
  --margin: 6px;
  width: 100%;
  display: grid;
  grid-template-columns: 70% calc(30% - var(--margin));
  gap: calc(var(--margin) * 2);
  padding: var(--margin);
}

.flex-col {
  padding: 0px;
  background-color: black;
  display: flex;
  justify-content: center;
  flex: 1;
  color: white;
}

@media screen and (max-width: 560px) {
  .container {
    flex-wrap: wrap;
  }
  .wrapper {
    --margin: 0px;
    grid-template-columns: 1fr;
  }
}
<div class="container">
  <div class="sidebar-menu-col">menu here</div>
  <div class="wrapper">
    <div class="flex-col">A1</div>
    <div class="flex-col">B1</div>
    <div class="flex-col">A2</div>
    <div class="flex-col">B2</div>
  </div>
</div>

Related