Right-align items in a flex container - html

I have a div container (black outline) which contains 4 divs of equal length and height.
I want the 4 colored divs to be aligned right with equal spaces between them (assuming that each colored div is about 49.5% the height of container and width of each div is about 25% of container).
I tried to do this with flex but I'm not getting what I want.
Can someone please help me? Thank you so much in advance.
<div class="container">
<div class="blue"></div>
<div class="red"></div>
<div class="purple"></div>
<div class="green"></div>
</div>
.container { }
.blue { }
.red { }
.purple { }
.green { }

Because it seems that you have two columns inside a row, I suggest you use three flexboxes for this occasion.
Here is how this works:
.container (outer flexbox, flex-direction: row)
-------------------------------------------------------------------
| .innerContainer | .innerContainer | .innerContainer |
-------------------------------------------------------------------
.innerContainer (inner flexbox, flex-direction: column)
--------------- --------------- --------------
| (empty) | | .blue | | .red |
--------------- | .purple | | .green |
--------------- --------------
Also, all flex-box children were set to flex-grow: 1 so that they are all equal dimensions and they fill up the entire space.
.container {
display: flex;
flex-direction: row;
background-color: #e9e9e9;
height: 100px;
}
.innerContainer {
display: flex;
flex-direction: column;
}
.blue, .red, .purple, .green, .innerContainer {
flex-grow: 1;
margin: 2px 1px;
}
.blue {
background-color: blue;
}
.red {
background-color: red;
}
.purple {
background-color: purple;
}
.green {
background-color: green;
}
<div class="container">
<div class="innerContainer"></div>
<div class="innerContainer">
<div class="blue"></div>
<div class="purple"></div>
</div>
<div class="innerContainer">
<div class="red"></div>
<div class="green"></div>
</div>
</div>

* { box-sizing: border-box; }
.container {
display: flex; /* create flex container */
flex-direction: column; /* align children vertically */
flex-wrap: wrap; /* allow multiple columns */
align-content: flex-end; /* shift columns to container end */
height: 100px;
width: 400px;
border: 2px solid black;
}
.container > div {
margin: 5px; /* equal spacing between divs */
width: calc(25% - 10px); /* width less margin */
height: calc(50% - 10px); /* height less margin */
}
.blue { background-color: blue; }
.purple { background-color: purple; }
.red { background-color: red; }
.green { background-color: green; }
<div class="container">
<div class="blue"></div>
<div class="purple"></div>
<div class="red"></div>
<div class="green"></div>
</div>
jsFiddle

Related

Position absolute but relatif

Currently I use this CSS to place a div (.child_bottom) at the bottom of its parent and another div above it (.child) because I know the height of (.child_bottom).
The parent at a variable height.
.parent
{
position:relative;
}
.child
{
position:absolute;
bottom:250px;
}
.child_bottom
{
position:absolute;
bottom:0;
height:250px;
}
<div class="parent">
<div class="child"></div>
<div class="child_bottom"></div>
</div>
But I would like to obtain the same thing with a variable height of .child_bottom, how to do?
Thank you in advance for your help.
Using flex would allow you to remove all of the absolute positioning:
.parent {
height: 400px;
outline: 1px solid blue;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.child {
background: green;
}
.child_bottom {
background: orange;
height: 250px;
}
<div class="parent">
<div class="child">CHILD</div>
<div class="child_bottom">CHILD_BOTTOM</div>
</div>
If you did wish to add content before .child, remove the justify-content and make this content flex: 1:
.parent {
display: flex;
flex-direction: column;
/* justify-content: flex-end; */
height: 400px;
outline: 1px solid blue;
}
.child {
background: green;
}
.child_bottom {
background: orange;
height: 250px;
}
.other_content {
background: yellow;
flex: 1;
}
<div class="parent">
<div class="other_content">
OTHER_CONTENT (Fills the space)
</div>
<div class="child">CHILD</div>
<div class="child_bottom">CHILD_BOTTOM</div>
</div>

Layout with 2 columns and 2 rows

I have a .container
with 2 columns and in the second column .right I want to have 2 rows
but the first row .content should use the remaining space
this is the HTML markup
<div class="container">
<div class="left">left</div>
<div class="right">
<div class="content">content</div>
<div class="footer">footer</div>
</div>
</div>
this is the CSS
.container {
display: flex;
flex-direction: row;
height: 400px; /* the remaining space in the screen will be nice */
}
.left {
width: 300px;
}
.right {
flex-grow: 1;
}
.content {
align-self: stretch; /* this is not doing anything*/
}
.footer {
}
and this is how it should look
+--------+----------------------+
| | |
| | |
| | content |
| left | |
| | |
| +----------------------+
| | footer |
+--------+----------------------+
You can use a full height flexbox container:
nest a column flexbox inside for the right element,
use flex-grow: 1 on content to occupy remaining space.
See demo below:
body {
margin: 0;
}
.container {
display: flex;
/* flex-direction: row; <-- omit this, its default */
height: 100vh; /* full height */
}
.left {
width: 300px;
border: 1px solid;
}
.right {
flex-grow: 1; /* occupy remaining space */
display: flex;
flex-direction: column; /* column flexbox */
border: 1px solid;
}
.content {
flex-grow: 1; /* occupy remaining space */
border-bottom: 1px solid;
}
<div class="container">
<div class="left">left</div>
<div class="right">
<div class="content">content</div>
<div class="footer">footer</div>
</div>
</div>
Flexbox works just fine here but I wanted to point out this is also a perfect situation for CSS Grid. With grid you can get rid of the extra container div.right.
<div class="container">
<div class="left">left</div>
<div class="content">content</div>
<div class="footer">footer</div>
</div>
.container {
display: grid;
grid-template-columns: 300px 1fr;
grid-template-rows: 1fr 100px; /* change the 100px to your desired height of the footer*/
grid-template-areas:
'left content'
'left footer';
height: 400px; /* height OP selected */
}
.left {
grid-area: left;
}
.content {
grid-area: content;
}
.footer {
grid-area: footer;
}
A CodePen just for fun.
Working example jsfiddle
.container {
display: flex;
flex-direction: row;
height: 100VH;
}
.left {
width: 200px;
border: 1px solid;
}
.right {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.content {
border: 1px solid #333;
border-bottom: 0;
flex-grow: 1;
}
.footer {
border: 2px solid;
height: 100px;
}

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>

Flexible width divs next to a fixed width div

Today I'm facing a challenging situation (at least for me).
Actually I have to make some divs flexible inside a parent div and having another fixed div as a 'brother'. These flexible divs must be 100% according to the width of their parent.
Here you go a picture made to explain my situation:
I was thinking something like:
.parent {
width: 500px; /* this value can change any time */
padding: 10px;
border: 1px solid red;
float: left;
}
.parent div {
float: left;
border: 1px solid #ccc;
}
.fixed {
width: 100px;
height: 100px;
background: #ccc;
}
.flexible {
width: calc(100% - 100px); /* IT IS NOT WORKING AS I WOULD LIKE */
}
<div class='parent'>
<div class='fixed'>*fixed</div>
<div class='flexible'>*flexible 1</div>
<div class='flexible'>*flexible 2</div>
</div>
Someone could help me?
Thanks
You can use flexbox for this. You should wrap your two flexible divs in a container so that they will stack. Then you can set the parent to display: flex; flex-direction: row;. Then set your flexible wrapper to display: flex; flex-direction: column; and set flex-grow: 1 on the flexible divs and the flexible wrapper so they expand to fill both the vertical and horizontal space.
.parent {
width: 500px;
padding: 10px;
border: 1px solid red;
display: flex;
flex-direction: row;
}
.parent div {
border: 1px solid #ccc;
}
.flexcontainer {
display: flex;
flex-direction: column;
flex-grow: 1;
}
.fixed {
width: 100px;
height: 100px;
background: #ccc;
}
.flexible {
flex-grow: 1;
}
<div class='parent'>
<div class='fixed'>*fixed</div>
<div class="flexcontainer">
<div class='flexible'>*flexible 1</div>
<div class='flexible'>*flexible 2</div>
</div>
</div>
You can use flexbox to achieve this layout.
.parent {
display: inline-flex; /* 1 */
padding: 10px;
border: 1px solid red;
}
.sub-container { /* 2 */
display: flex;
flex-direction: column;
align-items: stretch; /* 3 */
}
.flexible {
flex: 1; /* 4 */
border: 1px solid black;
}
.sub-container > div + div {
margin-top: 5px;
}
.fixed {
width: 100px;
height: 100px;
background: #ccc;
}
<div class='parent'>
<div class='fixed'>*fixed</div>
<div class='sub-container'>
<div class='flexible'>*flexible 1</div>
<div class='flexible'>*flexible 2 *flexible 2 *flexible 2</div>
</div>
</div>
Notes:
Inline-level flex container. (It adjusts to the width of its content.)
Create a sub-container for the flexible divs. Also uses flex properties.
An initial setting of a flex container is align-items: stretch. This means that flex items will automatically expand to cover the full length of the cross axis. In this case, that's the width.
Distribute the vertical space in the container evenly among the two flex items.
Taking your code as a base, you can add left and margin-left to .flexible. Also change the width as you need to calculate the padding and the container as well.
.flexible {
left: 0;
margin-left: 10px;
width: calc(100% - 120px); /* IT IS NOT WORKING AS I WOULD LIKE */
}

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>