Flex- change position of child's child? - html

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>

Related

Is flex's "align-items:flex-end" causing fixed-height divs inside flex-wrapped boxes to be vertically aligned according to each box's tallest one?

Doing a fairly basic HTML page I found myself perplexed by the following issue with flex in CSS.
First assume the following configuration:
A div wrapper with display: flex and applying justify-content: space-evenly, containing three inner boxes (could be more or less) each one also using flex (applying flex-wrap: wrap and align-items: end).
Each one of those inner boxes contains, in turn, two div elements: a top one and a bottom one (each with width: 100%); the bottom element has the same height while the top element has a different height per box; all of them are fixed heights in px.
This configuration looks more or less like this in HTML:
<div class="wrapper">
<div class="box">
<div class="top-element one"></div>
<div class="bottom-element one"></div>
</div>
<div class="box">
<div class="top-element two"></div>
<div class="bottom-element two"></div>
</div>
<div class="box">
<div class="top-element three"></div>
<div class="bottom-element three"></div>
</div>
</div>
And here's the CSS (written in SCSS to save space, I will include a snippet below where you can check the compiled CSS should you prefer); the commented line: "align-content: flex-end" indicates that I've already evaluated the effect of this property.
.wrapper {
display: flex;
justify-content: space-evenly;
.box {
display: flex;
align-items: flex-end;
// align-content: flex-end;
flex-wrap: wrap;
width: 30%;
.top-element {
width: 100%;
background-color: teal;
&.one {
height: 200px;
}
&.two {
height: 300px;
}
&.three {
height: 100px;
}
}
.bottom-element {
width: 100%;
background-color: lightblue;
&.one {
height: 100px;
}
&.two {
height: 100px;
}
&.three {
height: 100px;
}
}
}
}
Here's the snippet.
.wrapper {
display: flex;
justify-content: space-evenly;
}
.wrapper .box {
display: flex;
align-items: flex-end;
flex-wrap: wrap;
width: 30%;
}
.wrapper .box .top-element {
width: 100%;
background-color: teal;
}
.wrapper .box .top-element.one {
height: 200px;
}
.wrapper .box .top-element.two {
height: 300px;
}
.wrapper .box .top-element.three {
height: 100px;
}
.wrapper .box .bottom-element {
width: 100%;
background-color: lightblue;
}
.wrapper .box .bottom-element.one {
height: 100px;
}
.wrapper .box .bottom-element.two {
height: 100px;
}
.wrapper .box .bottom-element.three {
height: 100px;
}
<div class="wrapper">
<div class="box">
<div class="top-element one"></div>
<div class="bottom-element one"></div>
</div>
<div class="box">
<div class="top-element two"></div>
<div class="bottom-element two"></div>
</div>
<div class="box">
<div class="top-element three"></div>
<div class="bottom-element three"></div>
</div>
</div>
The issue is: It doesn't matter if you change the height of any of the top elements on any inner box, these remain vertically center-aligned according to the tallest element among all boxes, while the bottom ones remain at the bottom, and the space between top and bottom elements on each box is proportionally kept.
Now the question(s): is this correct css? and if so, I'm suspicious of align-items:"end" on each box to be the one to blame for this result, am I right? and if I'm wrong, why does this happen then?
Why didn't I use grid? well I'm in my flex phase... bear with me please.
You forget to define a vertical flex main direction for the elements with the CSS class .box.
Setting CSS property's flex-direction value to column for those elements fixes your problem.
SCSS
.box {
display: flex;
flex-direction: column;
...

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>

place two divs per row

so I have X divs and I want to put 2 divs in one row next to each other. If the screen size width is below n px there should be 1 div per row.
Currently I have this
#container {
display: flex;
}
.box {
width: 50px;
background: red;
}
#media(max-width: 300px) {
#container {
display: block;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2</div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>
How can I limit the flex box to two divs per row?
Add 50% width on .box and flex-wrap:wrap on the container
Additionally, what you did by changing display: flex to block was not required. Just change the .box elements width to 100%
#container {
display: flex;
flex-wrap: wrap;
}
.box {
width: 50%;
background: red;
}
#media(max-width: 300px) {
.box {
width: 100%;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2</div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>
Just add a property in your container class like
.container {
display: flex;
flex-wrap: wrap;
}
And in box class just specify the width of your box as 50% like
.box {
width: 50%;
background: red;
}
That should do the trick.
Flex will do a trick for you. flex-wrap: wrap for #container will make children wrap when necessary. .box with 50% and after breakpoint 100%.`
According to MDN:
The CSS flex-wrap property specifies whether flex items are forced into a single line or can be wrapped onto multiple lines. If wrapping is allowed, this property also enables you to control the direction in which lines are stacked.
If you are new to flexbox I recommend this guide.
Snippet
#container {
display: flex;
flex-wrap: wrap;
}
.box {
width: 50%;
background: red;
}
#media(max-width: 300px) {
.box {
width: 100%;
}
}
<div id="container">
<div class="box"> 1 </div>
<div class="box"> 2 </div>
<div class="box"> 3 </div>
<div class="box"> 4 </div>
</div>

How to shrink flex items height to fit container heights

I am trying to display a layout below in flex .
I have divs of equal width and height. I want to achieve the layout out below. By placing one item on the left and the remaining four fit on the right container and maintaining the same container height in the process . Thats the one on the left increase to fill the left height and width and the other right size of the container is shared among the four items.
.trades {
display: flex;
flex: 1;
}
.trade-panel {
flex: 1;
}
.layout-5-2 {
-ms-flex-direction: row;
flex-direction: row;
justify-content: space-between;
display: flex;
}
.layout-container-5-2-1 {
-ms-flex-direction: column;
flex-direction: column;
height: 100%;
justify-content: space-between;
flex: 0 0 48%;
display: flex;
}
.layout-container-5-2-2 {
flex: 0 0 48%;
display: flex;
flex-direction: column;
}
<div class="trades">
<div class="layout-5-2">
<div class="layout-container-5-2-1">
<div class="trade-panel">item 1</div>
<div class=" trade-panel">item 2</div>
<div class="trade-panel">item 3</div>
<div class=" trade-panel">item 4</div>
</div>
<div class="layout-container-5-2-1">
<div class="trade-panel">vertical item.</div>
</div>
</div>
</div>
My layout displays close to what i was expecting.with four to in the container to the right and one item to the left. However, The trades container scroll vertically to accommodate the four trades height. The trades does not shrink to fit into the right container thats .layout-container 5-2-2. Please how do i shrink the four to fix in the container heights ? Any help would be appreciated.
Try this
body,
html {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
display: flex;
min-height: 100vh;
background: #2A3052;
}
.left {
flex: 1;
background: #9497A8;
margin: 10px;
}
.right {
flex: 1;
display: flex;
flex-direction: column;
}
.box {
flex: 1;
background: #9497A8;
margin: 10px;
}
<div class="container">
<div class="left"></div>
<div class="right">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>