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>
Related
I cannot understand WHY I am not getting this:
.container {
width: 600px;
height: 400px;
border: 3px solid green;
}
.cg-panel {
display: flex;
flex-flow: column;
align-items: stretch;
justify-content: center;
}
.cg-panel .content {
flex: 1;
background-color: tomato;
}
<div class="container">
<div class="cg-panel">
<div class="content"></div>
</div>
</div>
I, for the life of me, cannot understand why the content panel does not vertically stretch the entire container. What is the purpose of "flex:1" if it isn't going to work? Am I not reading the documentation correctly?
There's nothing in your CSS that is expanding the height of .cg-panel to fit its parent .container.
Adding height: 100%; to .cg-panel fixes this:
.container {
width: 600px;
height: 400px;
border: 3px solid green;
}
.cg-panel {
display: flex;
flex-flow: column;
align-items: stretch;
justify-content: center;
height: 100%; /* add this */
}
.cg-panel .content {
flex: 1;
background-color: tomato;
}
<div class="container">
<div class="cg-panel">
<div class="content"></div>
</div>
</div>
My use case is the following:
I've got a center-aligned layout with a max-width of say 360px.
Part of that layout is a container with two adjacent boxes. The right one contains an image that fills 33% width of the window. Left to it should be a text container. This text container should be aligned with the left border of the remaining center-aligned layout.
Here's a sketch of it:
body {
display: flex;
flex-direction: column;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.items-end {
align-items: flex-end;
}
.items-start {
align-items: flex-start;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.left-content {
max-width: 240px;
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
<div class="col items-center">
<div class="top"></div>
</div>
<div class="row">
<div class="width-2-3 col items-end">
<div class="left-content">text</div>
</div>
<div class="width-1-3 col items-start">
<div class="right-content">[img]</div>
</div>
</div>
So basically my goal is to left align those two rows, no matter how big the window width. But after trying for some time I just can't get the math right! So any help would be greatly appreciated :)
You can consider negative margin left:
body {
display: flex;
flex-direction: column;
margin:0;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.left-content {
max-width: 240px;
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
#media (min-width:360px) {
.left-content {
margin-left:calc((150% - 360px)/2); /* 150 is 3/2*100% since the width is 2/3*/
}
.right-content {
margin-left:calc(240px + ((200% - 360px)/2) - 150%); /*200% is equal to 150% of the left element */
}
}
<div class="col items-center">
<div class="top"></div>
</div>
<div class="row">
<div class="width-2-3 col">
<div class="left-content">text</div>
</div>
<div class="width-1-3 col">
<div class="right-content">[img]</div>
</div>
</div>
Thanks to #temani-afif I came up with a solution that required only one line to change
- max-width: calc(240px);
+ max-width: calc(180px + 25%);
This way the text container is always left aligned to the top container while taking all the available space until the 33% window-width image container starts. And this works for all window sizes. Thanks for your help everyone! :)
body {
display: flex;
flex-direction: column;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.items-end {
align-items: flex-end;
}
.items-start {
align-items: flex-start;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.left-content {
max-width: calc(180px + 25%);
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
<div class="col items-center">
<div class="top"></div>
</div>
<div class="row">
<div class="width-2-3 col items-end">
<div class="left-content">text</div>
</div>
<div class="width-1-3 col items-start">
<div class="right-content">[img]</div>
</div>
</div>
Why dont you get rid of .item-end and .item-start divs so you can easily control the content.
body {
display: flex;
flex-direction: column;
}
.container {
position:relative;
max-width:360px;
width:100%;
display:flex;
justify-content:center;
}
.different-width {
max-width:450px;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
}
.items-center {
align-items: center;
}
.content-center {
justify-content:center;
}
.top {
max-width: 360px;
width: 100%;
height: 50px;
background: tomato
}
.left-content,
.right-content {
width: 100%;
height: 50px;
}
.width-2-3 {
width: 66.666%;
}
.width-1-3 {
width: 33.3333%
}
.left-content {
max-width: 240px;
background: rebeccapurple;
color: white;
}
.right-content {
background: pink;
}
<div class="col items-center">
<div class="container">
<div class="top"></div>
</div>
</div>
<div class="row content-center">
<div class="container different-width">
<div class="left-content width-1-3">text</div>
<div class="right-content width-2-3">[img]</div>
</div>
</div>
If you need to have more control over the left-content and right-content width, consider using flex-grow and flex-basis.
If you want to control the width of the second container, make another class with a different max-width value.
I need to center item (one) in 1/3 row space and center another item (two) in the rest of the row space (2/3).
https://jsfiddle.net/gpe9a5qb/1/
How to center items to the specific space they fit so they will NOT center depends on their size but depend on the size of the space they are signed (1/3 and 2/3)?
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
.one should be center inside 1/3 and .two must be center inside 2/3 space.
If i get this correctly, you are speaking about center horizontally.
the css will look like this
body
{border:1px dotted yellow;
margin:0;
padding:0;
width:100%;
height:100%;
background:brown;}
.container{
background:red;
width:250px;
height:100px;}
.box
{display:flex;
}
.box > div{
display:flex;
justify-content:center;
}
.one
{
background:green;
flex-basis:33.33%;
}
.two
{background:blue;
flex-basis:66.66%;}
Hope this helps.
What i did here, is that i put flex on the inside divs, and center their content(not the parent container, which you cant center , because they take up the space).
You were almost there. Just one modification needed:
Make each flex item a flex container with justify-content: center.
That's it.
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
/* justify-content: space-around */ /* remove; doing nothing */
}
.one {
background: green;
flex: 1 1 auto;
/* NEW */
display: flex;
justify-content: center;
}
.two {
background: blue;
flex: 2 1 auto;
/* NEW */
display: flex;
justify-content: center;
}
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
If I understand you correctly, you want both your .one and .two elements to be vertically centered inside of .box, whilst still taking up one-third and two-thirds of the space respectively.
In order to achieve this, you simply need to ensure that .box takes up the full height of .container.
You can achieve this by either setting display: flex on .container along with flex: 1 on .box:
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
display: flex;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
flex: 1;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
Or simply by setting height: 100% on .box:
body {
border: 1px dotted yellow;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: brown;
}
.container {
background: red;
width: 250px;
height: 100px;
}
.box {
display: flex;
align-items: center;
justify-content: space-around;
height: 100%;
}
.one {
background: green;
flex: 1 1 auto;
}
.two {
background: blue;
flex: 2 1 auto;
}
<div class="container">
<div class="box">
<div class="one">1/3</div>
<div class="two">2/3</div>
</div>
</div>
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;
}
This question already has answers here:
Remove space (gaps) between multiple lines of flex items when they wrap
(1 answer)
How does flex-wrap work with align-self, align-items and align-content?
(2 answers)
Closed 5 years ago.
Here's my example code:
#parent {
display: flex;
height: 350px;
background: yellow;
}
#wrapper {
flex: 1;
display: flex;
flex-flow: row wrap;
margin: 0 10%;
background: #999;
}
#top {
flex: 1 100%;
height: 50px;
margin-top: 10px;
background: red;
}
#left {
width: 30%;
height: 150px;
margin: 10px 10px 0 0;
background: blue;
}
#right {
flex: 1;
margin: 10px 0 0 0;
background: green;
}
<div id="parent">
<div id="wrapper">
<div id="top"></div>
<div id="left"></div>
<div id="right"></div>
</div>
</div>
As you can see, there's a gap (big gray area) between top (red) and left/right (blue/green). Flexbox seems to be spreading everything equally in parent element (gray).
However, I don't want the gap between my elements, I need everything to "rise" to top. There can be a gap after all elements (at the end).
I tried everything I could find/think of: auto margins, justify-content, align-items etc. No desired effect.
How to achieve this?
You need to add align-content: flex-start on flex-container or in your case #wrapper element.
#parent {
display: flex;
height: 350px;
background: yellow;
}
#wrapper {
flex: 1;
display: flex;
flex-flow: row wrap;
margin: 0 10% 50px 10%;
background: #999;
align-content: flex-start; /* Add this*/
}
#top {
flex: 1 100%;
height: 50px;
margin-top: 10px;
background: red;
}
#left {
width: 30%;
height: 150px;
margin: 10px 10px 0 0;
background: blue;
}
#right {
flex: 1;
margin: 10px 0 0 0;
background: green;
}
<div id="parent">
<div id="wrapper">
<div id="top"></div>
<div id="left"></div>
<div id="right"></div>
</div>
</div>
In a multi-line flex row layout, the align-content controls how the flex items aligns vertical when they wrap, and since its default is stretch, this is expected behavior.
Change it to align-content: center; and you'll see how their alignment change to vertical middle.
#parent {
display: flex;
height: 350px;
background: yellow;
}
#wrapper {
flex: 1;
display: flex;
flex-flow: row wrap;
margin: 0 10% 50px 10%;
background: #999;
align-content: center;
}
#top {
flex: 1 100%;
height: 50px;
background: red;
}
#left {
width: 30%;
height: 150px;
background: blue;
}
#right {
flex: 1;
background: green;
}
<div id="parent">
<div id="wrapper">
<div id="top"></div>
<div id="left"></div>
<div id="right"></div>
</div>
</div>