89

Hello fellow programmers!

I've got a simple box-layout which I would love to achieve using flexbox, but I simply can't figure it out. It should look like this image.

enter image description here

So basically a row and two columns, with the row being fixed at lets say 100px in height, but all in one container. My code so far is:

#productShowcaseContainer {
  display: inline-flex;
  flex-flow: row wrap;
  height: 600px;
  width: 580px;
  background-color: rgb(240, 240, 240);
}

#productShowcaseTitle {
  display: inline-block;
  height: 100px;
  width: 100%;
  background-color: rgb(200, 200, 200);
}

#productShowcaseDetail {
  flex: 3;
  background-color: red;
}

#productShowcaseThumbnailContainer {
  flex: 2;
  background-color: blue;
}
<div id="productShowcaseContainer">
  <div id="productShowcaseTitle"></div>
  <div id="productShowcaseDetail"></div>
  <div id="productShowcaseThumbnailContainer"></div>
</div>

I know this can be achieved in many ways, but I would really prefer to use CSS Flex.

JGallardo
  • 11,074
  • 10
  • 82
  • 96
Androvich
  • 1,030
  • 1
  • 7
  • 11

3 Answers3

108

You've almost done it. However setting flex: 0 0 <basis> declaration to the columns would prevent them from growing/shrinking; And the <basis> parameter would define the width of columns.

In addition, you could use CSS3 calc() expression to specify the height of columns with the respect to the height of the header.

#productShowcaseTitle {
  flex: 0 0 100%; /* Let it fill the entire space horizontally */
  height: 100px;
}

#productShowcaseDetail,
#productShowcaseThumbnailContainer {
  height: calc(100% - 100px); /* excluding the height of the header */
}

#productShowcaseContainer {
  display: flex;
  flex-flow: row wrap;

  height: 600px;
  width: 580px;
}

#productShowcaseTitle {
  flex: 0 0 100%; /* Let it fill the entire space horizontally */
  height: 100px;
  background-color: silver;
}

#productShowcaseDetail {
  flex: 0 0 66%; /* ~ 2 * 33.33% */
  height: calc(100% - 100px); /* excluding the height of the header */
  background-color: lightgray;
}

#productShowcaseThumbnailContainer {
  flex: 0 0 34%;  /* ~ 33.33% */
  height: calc(100% - 100px); /* excluding the height of the header */
  background-color: black;
}
<div id="productShowcaseContainer">
  <div id="productShowcaseTitle"></div>
  <div id="productShowcaseDetail"></div>
  <div id="productShowcaseThumbnailContainer"></div>
</div>

(Vendor prefixes omitted due to brevity)


Alternatively, if you could change your markup e.g. wrapping the columns by an additional <div> element, it would be achieved without using calc() as follows:

<div class="contentContainer"> <!-- Added wrapper -->
    <div id="productShowcaseDetail"></div>
    <div id="productShowcaseThumbnailContainer"></div>
</div>
#productShowcaseContainer {
  display: flex;
  flex-direction: column;
  height: 600px; width: 580px;
}

.contentContainer { display: flex; flex: 1; }
#productShowcaseDetail { flex: 3; }
#productShowcaseThumbnailContainer { flex: 2; }

#productShowcaseContainer {
  display: flex;
  flex-direction: column;

  height: 600px;
  width: 580px;
}

.contentContainer {
  display: flex;
  flex: 1;
}

#productShowcaseTitle {
  height: 100px;
  background-color: silver;
}

#productShowcaseDetail {
  flex: 3;
  background-color: lightgray;
}

#productShowcaseThumbnailContainer {
  flex: 2;
  background-color: black;
}
<div id="productShowcaseContainer">
  <div id="productShowcaseTitle"></div>

  <div class="contentContainer"> <!-- Added wrapper -->
    <div id="productShowcaseDetail"></div>
    <div id="productShowcaseThumbnailContainer"></div>
  </div>
</div>

(Vendor prefixes omitted due to brevity)

Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
  • Well, it worked, so thanks! I remember using another method with CSS Flex some time ago, but that might have been before the changes applied to flex. There the height was filled out automatically, since the row was set to "flex: 1 [something more]". – Androvich Oct 02 '14 at 15:35
  • @martinandrovich You are welcome. It seems the method you mentioned is the second one I've presented in my answer :-) – Hashem Qolami Oct 02 '14 at 15:57
  • Thanks @HashemQolami for useful smippet – Ana DEV Feb 20 '18 at 18:58
  • I had to add a flex-wrap to my container to perform this solution. – Sylvain Martin Mar 02 '19 at 14:41
6

Just use another container to wrap last two divs. Don't forget to use CSS prefixes.

#productShowcaseContainer {
   display: flex;
   flex-direction: column;
   height: 600px;
   width: 580px;
   background-color: rgb(240, 240, 240);
}

#productShowcaseTitle {
   height: 100px;
   background-color: rgb(200, 200, 200);
}

#anotherContainer{
   display: flex;
   height: 100%;
}

#productShowcaseDetail {
   background-color: red;
   flex: 4;
}

#productShowcaseThumbnailContainer {
   background-color: blue;
   flex: 1;
}
<div id="productShowcaseContainer">
   <div id="productShowcaseTitle">1</div>
   <div id="anotherContainer">
      <div id="productShowcaseDetail">2</div>
      <div id="productShowcaseThumbnailContainer">3</div>
   </div>
</div>
w411 3
  • 2,594
  • 2
  • 18
  • 21
2

This is copied from above, but condensed slightly and re-written in semantic terms. Note: #Container has display: flex; and flex-direction: column;, while the columns have flex: 3; and flex: 2; (where "One value, unitless number" determines the flex-grow property) per MDN flex docs.

#Container {
  display: flex;
  flex-direction: column;
  height: 600px;
  width: 580px;
}

.Content {
  display: flex;
  flex: 1;
}

#Detail {
  flex: 3;
  background-color: lime;
}

#ThumbnailContainer {
  flex: 2;
  background-color: black;
}
<div id="Container">
  <div class="Content">
    <div id="Detail"></div>
    <div id="ThumbnailContainer"></div>
  </div>
</div>
DeBraid
  • 8,751
  • 5
  • 32
  • 43