Flexbox stacked on small devices - css

I have 3 row grid, which is like this
https://codepen.io/Ramlev/pen/pXaqdg
<div class="container">
<div class="first">asd</div>
<div class="second">asd</div>
<div class="third">asd</div>
</div>
and the stylesheet
.container {
display: flex;
flex-direction: row;
}
.first {
flex: 1 0 250px;
background-color: red;
height: 400px;
}
.second {
flex: 1 0 250px;
background-color: green;
height: 200px;
}
.third {
flex: 1 0 250px;
background-color: blue;
height: 200px;
}
But when i go to a smaller device, i want the third row to fall under second row, and keep those two stacked to the right of the first row.
Does that make any sense?

You can clean up your code to start with by removing the flex shrink of 0 and the 250px flex basis since you really want halves and thirds with no real minimum width. By adding another wrapper around columns 2 and 3 and using a media query, you can get exactly what you described.
The mobile first default style can be achieved if the first column and the wrapper of columns 2 and 3 both have flex grow set to 1.
Then, once the breakpoint is reached, set the flex-grow property of the wrapper to 2 so it will be twice as big as column 1 and set it to display flex so it stops stacking columns 2 and 3.
.container {
display: flex;
flex-direction: row;
}
.first {
flex: 1;
background-color: red;
height: 400px;
}
.wrapper {
flex: 1;
}
#media only screen and (min-width: 500px) {
.wrapper {
display: flex;
flex: 2;
}
}
.second {
flex: 1;
background-color: green;
height: 200px;
}
.third {
flex: 1;
background-color: blue;
height: 200px;
}
<div class="container">
<div class="first">asd</div>
<div class="wrapper">
<div class="second">asd</div>
<div class="third">asd</div>
</div>
</div>

Related

CSS: Trying to test behavior of flex-shrink but can't see it working

I have 3 flex boxes in a row. On the first one, class .one, I have flex: 1 1 400px. I thought that would allow the box that is set to 400px be able to shrink but it's stayed at 400px when I lower the screen width.
I also see no difference when I do flex: 1 0 400px .
div.cont {
display: flex;
width: 100%;
}
div > div {
height: 90px;
width: 90px;
background: green;
}
.one {
background: green;
flex: 1 1 400px;
}
.two {
background: blue;
flex: 1;
}
.three {
background: pink;
flex: 1;
}
<div class="cont">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>

How to keep two columns on top of each other and other column to the right in bootstrap?

I am just wondering if it's possible in flexbox (without javascript or positioning or css grid) to change the layout like this. On desktop
and on phone it should look like below
I am using bootstrap 4, and there is option to change order but even that is not able to fulfill the expectation.
i am able to achieve the functionality using float
<div class="container">
<div class="float-none float-lg-left col-lg-6">1</div>
<div class="float-none float-lg-right">2</div>
<div class="float-none float-lg-left col-lg-6">3</div>
</div>
I know i'm a bit late to the question, not entirely Bootstrap 4 flexbox either - but you can do this with display:flex and a media query. You just need to set a height on the parent (in this case .wrapper), so that boxes 1 and 3 are '50%' of this height.
View the snippet full screen to see the switch of the boxes:
.wrapper {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
}
.box1 {
background: #31d1d3;
}
.box2 {
background: #bce9e2;
}
.box3 {
background: #62b1b7;
}
#media screen and (min-width:797px) {
.box2 {
order: 3;
}
.box1,
.box3 {
flex: 0 0 50%;
width: 50%;
}
.box2 {
flex: 0 0 100%;
width: 50%;
}
}
<div class="container">
<div class="wrapper">
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</div>
</div>
Without CSS grid it is possible BUT Column 2 MUST be smaller than Column 1 and Column 3 combined.
* {
box-sizing: border-box;
}
.box {
border: 1px solid grey;
}
#media (min-width: 576px) {
.wrapper {
padding-right: 50%;
position: relative;
}
.box--2 {
position: absolute;
height: 100%;
right: 0;
top: 0;
width: 50%;
}
}
<div class="wrapper">
<div class="box">Column 1</div>
<div class="box box--2">Column 2</div>
<div class="box">Column 3</div>
</div>
The size of .wrapper would be calculated from the height of the elements in flow (Column 1 and Column 3). If Column 2 is taller than those two, it will overflow out of the wrapper and there's nothing you can do to fix that without JavaScript.
Honestly, using CSS Grid (with IE fallbacks) is the better solution.

Keeping a child div from expanding a flexbox div

Well, here on this fiddle I have two divs aligned with display:flex and flex-grow: https://jsfiddle.net/h7bm23ts/2/
window.longer = function() {
document.getElementsByClassName("child2")[0].innerHTML += "like this and ";
};
* {
font-family: sans-serif;
}
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.box1 {
background-color: beige;
height: 300px;
flex-grow: 2;
}
.box2 {
background-color: cyan;
height: 300px;
flex-grow: 1;
}
.child1 {
background-color: green;
}
.child2 {
background-color: gray;
}
<div class="wrapper">
<div class="box1">
some nonsense
</div>
<div class="box2">
longer nonsense <button onclick="window.longer();"> even longer </button>
<div class="child1">
this child should be able to expand this div
</div>
<div class="child2">
this child should wrap when too much content is appended
</div>
</div>
</div>
However, the content in one of the divs is dynamic and when more content is appended onto a child div of it, the parent div expands and makes the boxes wrap, ruining the layout with a few button clicks.
How do I keep the gray div from expanding on more content and make it simply accept its parent's width as "strict" and wrap in it?
EDIT: I settled on https://jsfiddle.net/h7bm23ts/12/.
Try this css to achive what you need:
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.box1 {
background-color: beige;
min-height: 300px;
flex: 2 1 0; /* 2 - flex grow, 1 - flex shrink, 0 - flex basis */
}
.box2 {
background-color: cyan;
min-height: 300px;
flex: 1 0 0;
}
More about this You can find here:
https://css-tricks.com/flex-grow-is-weird/ and here: https://drafts.csswg.org/css-flexbox/#flex-grow-property, and
https://drafts.csswg.org/css-flexbox/#flexibility

Moving certain containers to sides without harming other containers

I've been looking around and could not find a way to move specific containers to the sides of the page, whilst leaving the other containers intact.
What I would would like to achieve is the following layouts for mobile and desktop screens, respectively: Desktop and Mobile
Note the colors: the third row on the mobile layout should become a left column on the desktop layout, and the fifth row on the mobile layout should become a right column on the desktop layout.
The rest of the rows should stay as a middle column on desktops.
I was trying to achieve that by using Flexbox but could not get it to done properly.
I would love to hear suggestions.
Thanks!
Seemed like an interesting exercise. It's a bit rough but the basics are there.
Codepen demo
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
body {
min-height: 100%;
}
.wrap {
height: 100%;
border: 1px solid grey;
display: flex;
flex-direction: column;
}
.child,
.aside {
flex: 1;
background: plum;
order: 1;
}
.aside {
background: #c0ffee;
}
#media screen and (min-width: 760px) {
.wrap {
flex-wrap: wrap;
}
.child {
order: 2;
width: 80%;
flex: 1 0 25%;
}
.left {
order: 1;
width: 10%;
flex: 0 0 100%;
}
.right {
order: 3;
width: 10%;
flex: 0 0 100%;
}
}
<div class="wrap">
<div class="child">One</div>
<div class="child">Two</div>
<div class="aside left">Three</div>
<div class="child">Four</div>
<div class="aside right">Five</div>
<div class="child">Six</div>
</div>

CSS Flex Box Layout: full-width row and columns

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.
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.
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)
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>
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>

Resources