Flexbox spanning a row - html

I am new to flex box. I thought of creating a structure like this
I tried to create this but the last <div> d is always coming in a different row
http://codepen.io/srajagop/pen/wzyNVL
body {
margin: 0;
}
.foo {
display: flex;
flex-wrap: wrap;
flex-direction: row;
display: -webkit-flex;
-webkit-flex-wrap: wrap;
-webkit-flex-direction: row;
height: 400px;
}
.a, .d {
flex: 0 0 50%;
background: green;
height: 200px;
}
.b,.c {
flex: 0 0 25%;
height: 400px;
background: blue;}
.c {
background: red;}
.d {
background: grey;
}
How to solve this?

I wouldn't add a margin top property like the above answer. What you really need is a nested flex container, where you have a row flex container surrounding all items, then a column flex container surrounding a and b. Here is a snippet that generally outlines the idea:
.row,
.col {
display: flex;
}
.row {
flex-direction: row;
height: 400px;
}
.col {
flex: 0 0 50%;
flex-direction: column;
}
.a,
.b {
flex: 0 0 50%;
}
.a {
background-color: green;
}
.b {
background-color: red;
}
.c,
.d {
flex: 0 0 25%;
}
.c {
background-color: blue;
}
.d {
background-color: yellow;
}
<div class="row">
<div class="col">
<div class="a"></div>
<div class="b"></div>
</div>
<div class="c"></div>
<div class="d"></div>
</div>

Used the margin-top property. Seems working.
body {
margin: 0;
}
.foo {
display: flex;
flex-wrap: wrap;
flex-direction: row;
display: -webkit-flex;
-webkit-flex-wrap: wrap;
-webkit-flex-direction: row;
height: 400px;
}
.a,
.d {
flex: 0 0 50%;
background: green;
height: 200px;
}
.b,
.c {
flex: 0 0 25%;
height: 400px;
background: blue;
}
.c {
background: red;
}
.d {
background: grey;
margin-top: -200px;
}
<div class="foo">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
</div>

Related

Make it so parent element not grow when child expands

I have a flex-box layout where I'm using flex-grow: 1 on multiple elements in order to distribute the layout evenly. However, when I add contents to one of the elements, it immediately expands out and ruins the even layout.
How can I make it so that the parents stay evenly distributed? Or would it be easier to just change it to width: 50% in order to fix that problem? Below is the code.
.app-container {
display: flex;
background: orange;
min-height: 100vh;
min-width: 100vw;
}
.sideBar-container {
display: flex;
background: pink;
width: 10%;
}
.info-container {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 100vh;
}
.top-container {
display: flex;
background: green;
flex-grow: 1;
}
.bottom-container {
flex-grow: 1;
display: flex;
background: wheat;
}
.top-left {
display: flex;
flex-direction: column;
background: blue;
flex-grow: 1;
}
.top-right {
display: flex;
background: red;
flex-grow: 1;
}
.top-two {
display: flex;
justify-content: space-around;
align-items: center;
flex-grow: 1;
background: gold;
}
.bottom-two {
display: flex;
justify-content: space-around;
align-items: center;
flex-grow: 1;
background: cornflowerblue;
}
.number-appts {
background: aqua;
flex-basis: 35%;
height: 45%;
}
.projected-revenue {
background: aquamarine;
flex-basis: 45%;
}
.projected-costs {
background: burlywood;
}
.projected-profit {
background: darkgray;
}
.appointment-consult {
background: seagreen;
}
<div className="app-container">
<div className="sideBar-container">
</div>
<div className="info-container">
<div className="top-container">
<div className="top-left">
<div className="top-two">
<div className="number-appts">test</div>
<div className="projected-revenue">this</div>
</div>
<div className="bottom-two">
<div className="projected-costs">here</div>
<div className="projected-profit">testing</div>
</div>
</div>
<div className="top-right">
<div className="appointment-consult"></div>
</div>
</div>
<div className="bottom-container"></div>
</div>
</div>
I figured it out. Changed my flex-grow: 1 to flex:1 as creating a rule where flex-basis is now 0px rather than auto stops the css from looking inward at the content

Flexbox (flex-direction: column): wrapped child not positioned correctly when one child has fixed width

I am using a flexbox layout with flex-flow: column wrap. I am setting a height for the flexbox container. What I am trying to achieve is to have the first child element take the whole height so that the next children will wrap to the the next column. In my case, those children are wrapping to the next column, however there is a huge space between their column and the column of the first child. It seems as though the fact that I set the width of the first child somehow affects the positioning of the wrapped children.
Here is what I try to achieve:
Here is the problem I am having:
Here is link to a codepen: codepen
.flex {
display: flex;
flex-flow: column wrap;
height: 100px;
border: 1px solid red;
}
.child1 {
background-color: green;
flex: 1 0 100%;
max-width: 100px;
}
.child2 {
flex: 1 0 20px;
background-color: yellow;
}
.child3 {
flex: 1 0 20px;
background-color: blue;
}
<div class="flex">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
I know this is a Flexbox question, but I'd like to throw CSS Grid into the mix. It's designed to handle both x/y layout directions. While flexbox can sometimes handle the y part, it is usually with greater difficulty/hacks.
.grid {
display: grid;
grid-template-columns: 100px 1fr;
grid-template-rows: repeat(2, 1fr);
height: 100px;
border: 1px solid red;
}
.child1 {
background-color: green;
grid-row: 1/-1; /* Begin at 1 and go to the end */
}
.child2 {
background-color: yellow;
}
.child3 {
background-color: blue;
}
<div class="grid">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
You need to set explicit width to your element. Acutally they are stretched by default.
If you remove the max-width you will have the following. Two eqaul columns where your element are stretched.
.flex {
display: flex;
flex-flow: column wrap;
height: 100px;
border: 1px solid red;
}
.child1 {
background-color: green;
flex: 1 0 100%;
}
.child2 {
flex: 1 0 20px;
background-color: yellow;
}
.child3 {
flex: 1 0 20px;
background-color: blue;
}
<div class="flex">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
Adding max-width will simply restrict the width of the first element in its column
.flex {
display: flex;
flex-flow: column wrap;
height: 100px;
border: 1px solid red;
}
.child1 {
background-color: green;
flex: 1 0 100%;
max-width:100px;
}
.child2 {
flex: 1 0 20px;
background-color: yellow;
}
.child3 {
flex: 1 0 20px;
background-color: blue;
}
<div class="flex">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
And if you change the alignment you will get this:
.flex {
display: flex;
flex-flow: column wrap;
height: 100px;
border: 1px solid red;
align-items:flex-start;
}
.child1 {
background-color: green;
flex: 1 0 100%;
}
.child2 {
flex: 1 0 20px;
background-color: yellow;
}
.child3 {
flex: 1 0 20px;
background-color: blue;
}
<div class="flex">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
You will see nothing because we removed the stretch alignment and there is no width defined.
Add some width to have the needed result:
.flex {
display: flex;
flex-flow: column wrap;
height: 100px;
border: 1px solid red;
align-items:flex-start;
}
.child1 {
background-color: green;
flex: 1 0 100%;
width:20%;
}
.child2 {
flex: 1 0 20px;
background-color: yellow;
width:80%;
}
.child3 {
flex: 1 0 20px;
background-color: blue;
width:80%;
}
<div class="flex">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>

How to stretch div to full height with flex

How do I stretch the divs with a yellow background to full height? It should cover up the green but it is not working. I tried adding height: 100% on it but then it adds up the height from the search bar?
https://jsfiddle.net/nuy20j1h/
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
width: 75%;
background: green;
}
.search-bar {
width: 100%;
padding: 25px;
background: blue;
}
.content-wrap {
display: flex;
flex-wrap: wrap;
width: 100%;
align-items: flex-stretch;
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
First you should add a style reset, I'm using this now * {} as you can se below. The trick here is to run flex-direction: column; on .home and you can tell .content-wrap to take up the rest of that space after the search with flex-grow: 1;
box-sizing: border-box; is, if you add let's say width: 200px; to a element, and add padding: 20px;, the element will stay 200px with the padding included. If you don't have that, it will take up 200px + 40px.
if you want the fiddle, here it is
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
width: 75%;
background: green;
}
.search-bar {
width: 100%;
padding: 25px;
background: blue;
}
.content-wrap {
display: flex;
flex-grow: 1;
flex-wrap: wrap;
width: 100%;
align-items: flex-stretch;
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
As mentioned in other answers, there is one main issue here:
flex-direction: column;, which I added to home, to enable the usage of flex properties instead of height, to make the .content-wrap fill the available space left in home
That will make the .search-bar and .content-wrap stack vertical, and enable the use of flex: 1 on .content-wrap, which will make it fill the remaining space/height.
So even if you got answers already, and since there are some properties with wrong value, or not needed, I decided to post an answer to clarify the changes made.
See my notes made in the CSS for further clarifications and what I changed.
Stack snippet
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-direction: column; /* added */
/*flex-wrap: wrap; removed, not needed */
/*align-items: flex-start; removed, items should fill parent's,
in this changed case, width */
width: 75%;
background: green;
}
.search-bar {
/*width: 100%; not needed, default for column
item is to fill parent width as
its "align-items" is "stretch" */
padding: 25px;
background: blue;
}
.content-wrap {
flex: 1; /* added, take the remaining space left
left of its parent (height in this case) */
display: flex;
flex-wrap: wrap;
/*width: 100%; not needed, default for column
item is to fill parent width as
its "align-items" is "stretch" */
/*align-items: flex-stretch; wrong value, should be "stretch",
though since that is the default,
it is not needed */
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
flex-direction: column; is your friend. Here is a reworked fiddle of your code: https://jsfiddle.net/vsjktmms/1/
Using the same HTML structure you provided:
.block {
display: flex;
width: 80%;
margin: 0 auto;
background-color: gray;
align-items: stretch;
}
.sidebar {
width: 25%;
height: 600px;
background-color: red;
}
.home {
display: flex;
flex-direction: column;
align-items: stretch;
width: 75%;
background-color: green;
}
.search-bar {
padding: 25px;
background-color: blue;
}
.content-wrap {
flex: 1 1 auto;
display: flex;
flex-wrap: wrap;
width: 100%;
background-color: pink;
}
.content,
.single {
width: 50%;
background: yellow;
}

rowspan or colspan in flexbox?

I am a backend programmer by profession. But I have just started to learn flexbox and I want to hit the sky with flexbox.
So, I created a simplest design but which looks most complicated to me when creating it using flexbox.
Here is the design:
Guys, I am not able to figure out, how to use flexbox in such a case as there is no row or column. I don't know but is there anything like rowspan or colspan in flexbox that I can use to arrange these divs as shown in image above?
Here is my code:
HTML:
<div class="wrapper">
<div class="div-wrapper1">
<div class="inner-wrapper1">
<div class="div1"></div>
<div class="fake1"></div>
</div>
<div class="div2"></div>
</div>
<div class="div-wrapper2">
<div class="div3"></div>
<div class="inner-wrapper2">
<div class="fake2"></div>
<div class="div4"></div>
</div>
</div>
<div class="div-center"></div>
</div>
CSS:
.wrapper {
height: 200px;
width: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.div-wrapper1 {
display: flex;
flex: 1;
}
.div-wrapper2 {
display: flex;
flex: 1
}
.inner-wrapper1 {
display: flex;
flex: 3;
flex-direction: column;
}
.div1 {
background-color: red;
display: flex;
flex: 3
}
.fake1 {
display: flex;
flex: 1
}
.div2 {
background-color: green;
display: flex;
flex: 2
}
.div3 {
background-color: blue;
display: flex;
flex: 2
}
.inner-wrapper2 {
display: flex;
flex: 3;
flex-direction: column;
}
.div4 {
background-color: yellow;
display: flex;
flex: 3
}
.fake2 {
display: flex;
flex: 1
}
.div-center {
background-color: black;
}
This is my output:
Here is the codepen
Maybe a solution is to simply add a negative margin to .div-wrapper1 and you will get the exact layout :
.wrapper {
height: 200px;
width: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.div-wrapper1 {
display: flex;
flex: 1;
}
.div-wrapper2 {
display: flex;
flex: 1;
margin-top: -30px;
}
.div-wrapper3 {
display: flex;
flex: 1
}
.inner-wrapper1 {
display: flex;
flex: 3;
flex-direction: column;
}
.div1 {
background-color: red;
display: flex;
flex: 3
}
.fake1 {
display: flex;
flex: 1
}
.div2 {
background-color: green;
display: flex;
flex: 2
}
.div3 {
background-color: blue;
display: flex;
flex: 2
}
.inner-wrapper2 {
display: flex;
flex: 3;
flex-direction: column;
}
.div4 {
background-color: yellow;
display: flex;
flex: 3
}
.fake2 {
display: flex;
flex: 1
}
.div-center {
background-color: black;
}
<div class="wrapper">
<div class="div-wrapper1">
<div class="inner-wrapper1">
<div class="div1"></div>
<div class="fake1"></div>
</div>
<div class="div2"></div>
</div>
<div class="div-wrapper2">
<div class="div3"></div>
<div class="inner-wrapper2">
<div class="fake2"></div>
<div class="div4"></div>
</div>
</div>
<div class="div-center"></div>
</div>
And if you want here is another solution without any negative values and a content inside the white part (simply adjust height/width as you need) :
.first,
.second {
display: flex;
height: 100px;
width: 200px;
}
.first:before {
content: "";
background: red;
flex: 3;
}
.first:after {
content: "";
background: green;
flex: 2;
}
.second:before {
content: "";
background: blue;
flex: 2;
}
.second:after {
content: "";
background: yellow;
flex: 3;
}
.fake {
display: flex;
height: 20px;
width: 200px;
}
.fake a {
flex: 1;
text-align: center;
}
.fake:before {
content: "";
background: blue;
flex: 2;
}
.fake:after {
content: "";
background: green;
flex: 2;
}
<div class="first">
</div>
<div class="fake">
link
</div>
<div class="second">
</div>
Here is another solution by simply using multiple linear-gradient:
.box {
display: flex;
height: 220px;
width: 200px;
justify-content: center;
align-items: center;
background-image:linear-gradient(to right,red 66%,green 0%),
linear-gradient(to right,blue 33%,white 0%,white 66%,green 66%),
linear-gradient(to right,blue 33%,yellow 0%);
background-size:100% 100px,100% 20px,100% 100px;
background-position:top,center,bottom;
background-repeat:no-repeat;
}
<div class="box">
link
</div>

Flexbox 3 divs, two columns, one with two rows

I am trying to take
<div></div>
<div></div>
<div></div>
Three sequential divs and turn it into below. Where red is div 1, green is div 2, blue is div 3.
I can do this with floats, something like
.div1 { float: left; }
.div2 { float: left; }
.div3 { float: left; }
But I can't seem to get it working in flexbox, is this possible?
The Legit Method:
*Recommended
.flex-row {
flex-direction: row;
display: flex;
}
.flex-column {
flex-direction: column;
display: flex;
}
.flex-body {
display: flex;
}
.flex-body div:not([class*="flex"]) {
border: 1px solid white;
flex: 1 1 200px;
width: 300px;
}
<div class="flex-body">
<div class="flex-row">
<div style="background: #0980cc;"></div>
</div>
<div class="flex-column">
<div style="background: #09cc69;"></div>
<div style="background: #cc092f;"></div>
</div>
</div>
The Hackish Method:
*Not Recommended (I'm sure you'll notice why)
.flex-body {
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
justify-content: flex-end;
align-content: stretch;
align-items: stretch;
transform: rotate(90deg);
max-width: 500px;
margin: auto;
}
.flex-body div {
border: 1px solid white;
height: 300px;
flex: 1 1 200px;
}
.flex-body div:last-of-type {
flex: 1 1 300px;
height: 300px;
}
<div class="flex-body">
<div style="background: #0980cc;"></div>
<div style="background: #09cc69;"></div>
<div style="background: #cc092f;"></div>
</div>
After thinking about this a little more, it is possible with flexbox. The container just has to have a defined height (%, px or vh) will work.
http://codeply.com/go/U1DCKAx85d
body {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 100vh;
}
.a {
flex: 0 0 100%;
background: red;
}
.b, .c {
flex: 0 0 50%;
background: green;
}
.c {
background: blue;
}
Using flexbox is very simple, you just need a container for these three div elements.
Let's define a div with a .box class and add the div elements. Also let's add three classes for the colors: .red, .green and .blue and two classes to handle the columns left and right.
<div class="box">
<div class="left red"></div>
<div class="right green"></div>
<div class="right blue"></div>
</div>
Now we define the box class as a flexbox:
.box {
display: flex;
...
}
Then we define the direction as column (vertical) and if it can be flowed wrap:
.box {
...
flex-flow: column wrap;
...
}
Also, we can define the dimensions of the div elements. left will be 45% of the parent width and 100% of the parent height.
.left {
width: 45%;
height: 100%;
}
While right will be 55% of the parent width and 50% (half) of the parent height.
.right {
width: 55%;
height: 50%;
}
Full example:
.box {
display: flex;
flex-flow: column wrap;
width: 400px;
height: 100px;
}
.red {
background: #cc092f;
}
.green {
background: #09cc69;
}
.blue {
background: #0980cc;
}
.left {
width: 45%;
height: 100%;
}
.right {
width: 55%;
height: 50%;
}
<div class="box">
<div class="left red"></div>
<div class="right green"></div>
<div class="right blue"></div>
</div>