Set two flex items side by side in a flexbox column - html

I have some elements I am displaying in a column direction within a display: flex container.
This places the containers within into a stacked view.
Say I have 5 stacked elements I need to make two of them display inline or flex direction row.
Without placing the two elements in question into another div that i can apply flex direction row to...
Is it possible to get these elements to sit side by side?
.flex-column {
display: flex;
flex-direction: column;
}
.flex-column .column-item:nth-of-type(4),
.flex-column .column-item:nth-of-type(5) {
width: calc(50% - 10px);
display: inline-block;
float: left;
}
.flex-column .column-item:nth-of-type(4) {
margin-right: 20px;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>

I don't think it is possible once you have given your parent the flex-direction:column; property, alternatively you can enable flex-wrap:wrap and control the width of elements using the flex-basis property. This allows you to achieve the effect you want without altering your html structure.
.flex-column {
display: flex;
flex-wrap:wrap;
}
.flex-column .column-item {
flex-basis:100%;}
.flex-column .column-item:nth-of-type(4),
.flex-column .column-item:nth-of-type(5) {
flex-basis:50%;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>

The layout is fairly simple with flexbox. You don't need flex-direction: column.
Just use flex-direction: row with flex-wrap: wrap.
Then make each element long enough to occupy a full row.
Reduce the flex-basis on the elements that are to share a row.
.flex-column {
display: flex;
flex-wrap: wrap;
}
.column-item {
flex: 1 0 61%; /* flex-grow, flex-shrink, flex-basis */
margin: 2px;
background-color: lightgreen;
}
.column-item:nth-of-type(4),
.column-item:nth-of-type(5) {
flex-basis: 40%;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>
With flex-grow: 1 defined in the flex shorthand, there's no need to use calc().
Since flex-grow will consume free space on the row, flex-basis only needs to be large enough to enforce a wrap. In this case, with flex-basis: 61%, there's plenty of space for the margins, but never enough space for a second item.
There's an even simpler and more efficient solution using CSS Grid:
.flex-column {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 5px;
}
.column-item:nth-of-type(-n + 3) {
grid-column: span 2;
}
.column-item {
background-color: lightgreen;
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>

.flex-column {
display: flex;
flex-wrap:wrap;
}
.column-item {
}
<div class="flex-column">
<div class="column-item">a</div>
<div class="column-item">b</div>
<div class="column-item">c</div>
<div class="column-item">d</div>
<div class="column-item">e</div>
</div>

Related

Flexbox: each element 1/3 width, fall under each other if not enough space [duplicate]

This question already has answers here:
How can I show three columns per row?
(4 answers)
Closed 1 year ago.
I am looking for a way (with Flexbox, not Grid) to create a layout, when I have a container with x cards inside, and each card inside should take 1/3 of the container width. So cards number 1,2,3 will be in the first row, cards number 4,5... in the second row etc.
I feel like it is impossible with flexbox, I don't wanna do some checks for number of items, I used map to map cards in containers of max 3 cards but I didn't like the solution. Before I move to using grid, I would love to get some insight if it is possible to acomplish with Flexbox.
The code is:
<div class="container">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
you should set box-sizing: border-box; on the cards so padding and borders are calculated in their width. and set their max-width: 33.33%.
body {
padding: 30px;
margin: 0;
}
.container {
display: flex;
flex-direction: row;
width: 100%;
flex-wrap: wrap;
background: orange;
}
.card {
box-sizing: border-box;
width: 100%;
text-align: center;
max-width: 33.33%;
padding: 50px 0;
background-color: aqua;
border: 1px solid #000;
}
<div class="container">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
</div>
The difference will be for the second row. There are two options for the last two element width.
Option 1 Last two nodes take 33% width only and leave the right side blank.
You have to use display: flex; flex-wrap: wrap; for .container and display: flex; flex: 0 1 33%; for the child element, which is .card.. Here flex-shrink is to be set for child
.container {
display: flex;
flex-wrap: wrap;
}
.card {
height: 100px;
display: flex;
flex: 0 1 33%;
justify-content: center;
align-items: center;
font-size: 50px;
}
<div class="container">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
</div>
Option 2 Last two element use 50% width each.
You have to use display: flex; flex-wrap: wrap; for container and display: flex; flex: 1 0 33%; to the child element, which is .card. Here flex-grow is to be set for child
.container {
display: flex;
flex-wrap: wrap;
}
.card {
height: 100px;
display: flex;
flex: 1 0 33%;
justify-content: center;
align-items: center;
font-size: 50px;
}
<div class="container">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
</div>
Flex-wrap can help you with that
.container{
display: flex;
flex-wrap: wrap;
}
.card{
min-width: 33.3333%;
}
Example here: https://codepen.io/jriches/pen/WNjVaav
Use 33.33333333% width in your card class.

Changing the size of individual element in flexbox

How can I stretch the items inside a div to fill the area, and is it possible to have the items in different sizes without having to modify individually using :nth-child(x). For instance: first, third and fifth item to be twice as big as second and fourth item?
.my_class_a {
display: flex;
align-items: center;
flex-wrap: wrap;
}
<div class="my_class_a">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c</div>
<div class="item">d</div>
<div class="item">e</div>
</div>
I do apologize because I don't know how to format in fiddle way.
How can I stretch the items inside a div to fill the area...
Use the flex-grow property.
and is it possible to have the items in different sizes without having to modify individually using :nth-child(x).
How is the browser supposed to know what you want if you don't define the behavior?
For instance: first, third and fifth item to be twice as big as second and fourth item?
In this case, you can use the even and odd functions of the nth-child() pseudo class.
.my_class_a {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.item:nth-child(odd) {
flex-grow: 2;
background-color: lightgreen; /* for demo only */
}
.item:nth-child(even) {
flex-grow: 1;
background-color: orange; /* for demo only */
}
/* for aligning item content */
.item {
display: flex;
align-items: center;
justify-content: center;
}
<div class="my_class_a">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c</div>
<div class="item">d</div>
<div class="item">e</div>
</div>
In general you can use flex-grow: 1; to allow flex items to become larger. (Note that i defined a width for the container, otherwise they won't grow)
Concerning your wish about the 2nd, 4th etc. item: You need to define * somewhere* which items should grow and which not, so you you need at least some kind of selector for them.
.my_class_a {
display: flex;
flex-wrap: wrap;
width: 100%;
align-items: center;
}
.item {
border: 1px solid #333;
flex-grow: 1;
padding: 12px;
text-align: center;
}
<div class="my_class_a">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c<br>c</div>
<div class="item">d</div>
<div class="item">e</div>
</div>
P.S.: To create a snippet (the "fiddle-line" code example, just click the 7th symbol in the toolbar of the answer window)
You can use the flex style declaration - it's a shorthand for:
flex-grow | flex-shrink | flex-basis
where flex-basis is the initial width of the flexbox child and flex-grow and flex-shrink determine how quickly the flexbox child will grow or shrink relative to its siblings.
For instance:
an element with flex: 2 2 100px starts with a width of 100px and will grow or shrink twice as fast as flex: 1 1 50px which starts with a width of 50px.
Working Example:
.my_class_a {
display: flex;
width: 100%;
align-items: center;
}
.item {
color: rgb(255, 255, 255);
text-align: center;
font-weight: bold;
}
.item-a,
.item-c,
.item-e {
flex: 2 2 100px;
background-color: rgb(255, 0, 0);
}
.item-b,
.item-d {
flex: 1 1 50px;
background-color: rgb(0, 0, 0);
}
<div class="my_class_a">
<div class="item item-a">a</div>
<div class="item item-b">b</div>
<div class="item item-c">c</div>
<div class="item item-d">d</div>
<div class="item item-e">e</div>
</div>

Aligning left right using Flex

So I have a code like this more or less
<div class="content">
<div class="c1">
<div>
<div class="c2">
<div>
<div class="c3">
<div>
<div class="c4">
<div>
</div>
By using flex, can I do this?
<c1> <c3>
<c2> <c4>
I know I can use <ul> or <table>, but I am just wondering if I can do it using flex. I have tried using flex but cannot accomplish it.
DEMO
Yes, this is possible with Flexbox - Set a height on the .content and the child divs (e.g. content: 100px, divs 50px) and specify flex-flow: column wrap
.content {
display: flex;
align-items: center;
justify-content: center;
flex-flow: column wrap;
align-content: stretch;
height: 100px;
}
.content div {
height: 50px;
width: 50px;
}
Flex-flow is shorthand for flex-direction and flex-wrap.
Flex-direction sets the direction - row, column, row-reverse, column-reverse.
Flex-wrap wraps the flexible items (or not). By default this is nowrap, the demo uses wrap and you can also use wrap-reverse
You can achieve this by modifying your markup to the following structure:
<div class="content">
<div class="left-col">
<div class="c1"><div>
<div class="c2"><div>
</div>
<div class="right-col">
<div class="c3"><div>
<div class="c4"><div>
</div>
</div>
Now you have two columns. Simply add the following styles to your CSS:
.content {
display: flex;
justify-content: space-between; // or whatever you want
flex-direction: row; // row is the default value, so you don't need to specify it. It will place the cols beside each other.
}
.left-col, .right-col {
display: flex;
flex-direction: column;
}
By specifying flex-direction: column; the elements will be positioned below each other.
Here's some great resource: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Maybe you also want to check out the new native grid-layout: https://www.w3schools.com/css/css_grid.asp
You can easily do this with CSS grid, this is in my opinion more useful to use but this is the code that uses CSS grid
HTML
<div class="content">
<div class="c1">test 1</div>
<div class="c2">test 2</div>
<div class="c3">test 3</div>
<div class="c4">test 4</div>
</div>
CSS:
.content {
display: grid;
grid-template-columns: 1fr 1fr;
}
And what about this trick ?
.content
{
display: flex;
flex-direction: column;
height: 50px;
flex-wrap: wrap;
}
<div class="content">
<div class="c1">1</div>
<div class="c2">2</div>
<div class="c3">3</div>
<div class="c4">4</div>
</div>
Yes you can do please consider below code.
HTML
<div class="content ">
<div class="col-12 d-flex justify-content-between">
<div class="c1 col-6 text-center">c1
</div>
<div class="c2 col-6 text-center">c2
</div>
</div>
<div class="col-12 d-flex justify-content-between">
<div class="c3 col-6 text-center">c3
</div>
<div class="c4 col-6 text-center">c4
</div>
</div>
</div>
CSS
.justify-content-around {
-ms-flex-pack: distribute!important;
justify-content: space-around!important;
}
.d-flex {
display: -webkit-box!important;
display: -ms-flexbox!important;
display: flex!important;
}

css flexbox 3-column layout where first is fixed width

I am trying to better understand flex box css and have a main layout for all pages. It is 3 columns where the first column is fixed width and the others can be any size so long as all 3 take up 100% width.
I believe the problem is in .col class but unsure how to set the 1st column and let the other grow. Thank you.
.wrapper {
display: flex;
flex-direction: row;
}
.col {
flex-basis: 25%;
align-items: stretch;
}
<div class="wrapper">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
You simply need to specify a fixed width to the first one and then set flex:1 to the other so they take the remaining space and fill 100% of the container space:
.wrapper {
display: flex;
flex-direction: row;
}
.col {
flex: 1;
background: red;
}
.col:first-child {
width: 100px; /* Or a percentage value */
flex:initial;
background: green;
}
<div class="wrapper">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>

Flex- change position of child's child?

I wish to get A to sit at the top, B to sit in the middle and C to sit at the bottom.
JSFiddle
<div class="container">
<div class="a">A</div>
<div class="sub-container">
<div class="b">B</div>
<div class="c">C</div>
</div>
</div>
CSS:
.container{
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
position: fixed;
}
i need to keep the same markup - how can I change the position of a div that is not the immediate child of the flex container?
EDIT:
It should look like this
A
B
C
The CSS Display Module Level 3 introduces display: contents:
The element itself does not generate any boxes, but its children and
pseudo-elements still generate boxes as normal. For the purposes of
box generation and layout, the element must be treated as if it had
been replaced with its children and pseudo-elements in the document
tree.
You can use it to "ignore" the subcontainer, and display all the inner items as if they belonged to the same container.
body { margin: 0 }
.container {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
position: fixed;
}
.sub-container {
display: contents;
}
<div class="container">
<div class="a">A</div>
<div class="sub-container">
<div class="b">B</div>
<div class="c">C</div>
</div>
</div>
It's not widely supported yet, though.
With this HTML code where .b and .c aren't siblings of .a, you can achieve desired result with a flex inception: .sub-container is both a flex item of parent .container and a flex container for .b and .c
flex: 2 0 auto; is related to height ratio of 1/3 + (1/3 + 1/3)
Fiddle
.container{
display: flex;
flex-direction: column;
justify-content: space-between;
width: 100%;
height: 100%;
position: fixed;
}
.sub-container {
flex: 2 0 auto;
/* flex inception */
display: flex;
flex-direction: column;
background-color: lightgreen;
}
.a, .b, .c {
flex: 1 0 auto; /* .a and .b, .c are not flex items of the same parent though we still want the same value */
padding: 1rem 0;
text-align: center;
}
<div class="container" style="background-color: blue;">
<div class="a" style="background-color: red;">A</div>
<div class="sub-container" style="background-color: green;">
<div class="b">B</div>
<div class="c">C</div>
</div>
</div>