I am making responsive design where elements wrap to next line in certain way when there is not enough space, however I cannot make it working.
Requirements:
There are 3 elements (actually more, but this is minimal example), all with automatic size depending on their content: one aligned on the left, two - on the right.
They are placed inside container which always spans at least 100% width of parent.
If there is not enough space for elements to be all on one line, then right element should begin to wrap to next line, while still all being to the right of left element.
If there is still not enough space, only then right elements go under left one.
If there is still not enough space, then container expands in size.
Here are examples how it should work (red lines represent viewport borders):
Here is code I come up with so far, but it starts wrapping immediately on outer level, not on innermost as I need:
html, body {
width: 100%;
height: 100%;
}
* {
margin: 0;
padding: 0;
flex: 0 0 auto;
}
#container {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
overflow: hidden;
width: 100%;
min-width: min-content;
background-color: rgb(224, 191, 146); /* for visibility */
}
#child-left {
background-color: rgb(92, 189, 40); /* for visibility */
/* imitate content for demo, in actual code size is not set */
width: 50vw;
height: 50px;
}
#child-right {
display: flex;
flex-flow: row wrap;
background-color: rgb(111, 72, 20); /* for visibility */
}
#grandchild-right-1 {
background-color: rgb(40, 102, 189); /* for visibility */
/* imitate content for demo, in actual code size is not set */
width: 200px;
height: 20px;
}
#grandchild-right-2 {
background-color: rgb(189, 40, 112); /* for visibility */
/* imitate content for demo, in actual code size is not set */
width: 200px;
height: 20px;
}
<div id="container">
<div id="child-left">1</div>
<div id="child-right">
<div id="grandchild-right-1">2</div>
<div id="grandchild-right-2">3</div>
</div>
</div>
You can achieve this by using flex: 1.
Remember that flex is a shorthand property for flex: 1 1 0 or flex-grow: 1, flex-shrink: 1 and flex-basis: 0.
As a result, this makes the elements take any empty space in the container, hopping to the next line if theres no space left.
https://css-tricks.com/understanding-flex-grow-flex-shrink-and-flex-basis/
Related
I have 3 buttons in a row which all vary in width. I want them to all gain width the same to fill the remaining width of the row, so the widest will still be wider than the others etc.
You can see below that what I've tried to do with flex has resulted in all the buttons being the same width. I know flex-grow can be used to proportionally grow each item, but I can't work out how to get them all to grow in relation to their original size.
You can see in the second row that the blue item is larger than the other two. I just want all three to expand from their current size equally to fill the row.
Thanks
.row-flex {
width: 100%;
display: flex;
flex-direction: row;
}
.button {
flex: 1;
display: inline-block;
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
<div class="row-flex">
Single
Larger title
Another really large title
</div>
<br/>
<div class="row">
Single
Larger title
Another really large title
</div>
Short Answer
Switch from flex: 1 to flex: auto.
Explanation
The flex-grow property factors in two key pieces of data:
The free space in the row / column where it is being used.
The value of the flex-basis property.
Distribution of Free Space
The flex-grow property distributes free space in the container among flex items in the same line.
If there is no free space, flex-grow has no effect.
If there is negative free space (i.e., the total length of flex items is greater than the length of the container), then flex-grow has no effect and flex-shrink comes into play.
The flex-basis factor
When flex-basis is 0, flex-grow ignores the size of the content in flex items and treats all space on the line as free space.
This is absolute sizing. All space on the line is distributed.
When flex-basis is auto, the size of the content in flex items is first deducted to determine the free space in each item. flex-grow then distributes the free space among items (based on each item's flex-grow value).
This is relative sizing. Only extra space on the line is distributed.
Here's an illustration from the spec:
Examples:
flex: 1 (absolute sizing)
This shorthand rule breaks down to: flex-grow: 1 / flex-shrink: 1 / flex-basis: 0
Applied to all flex items, this will make them equal length, regardless of content. (Note that in some cases an override of default minimum sizing will be necessary for this effect to occur.)
flex-grow: 1 (relative sizing)
This rule by itself will factor in both content size and available space, because the default value for flex-basis is auto.
flex: auto (relative sizing)
This shorthand factors in both content size and available space because it breaks down to:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
More variations here: 7.1.1. Basic Values of flex
additional keywords for search: difference between flex-basis auto 0 flex 1 auto
Not sure if this is entirely what you are after, but if you just set flex-grow:1 instead of flex:1;, I think that is your required result:
.row-flex {
width: 100%;
display: inline-flex;
flex-direction: row;
}
.button {
flex-grow: 1;
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
<div class="row-flex">
Single
Larger title
Another really large title
</div>
Using flex property you can set proportions:
.button {
display: inline-block;
padding: 10px;
color: #fff;
text-align: center;
}
.row {
display: flex;
}
.button--1 {
background: red;
flex: 1 1 auto;
}
.button--2 {
background: green;
flex: 2 1 auto;
}
.button--3 {
background: blue;
flex: 3 1 auto;
}
<br/>
<div class="row">
Single
Larger title
Another really large title
</div>
Minimalistic answer with (hopefully useful, explanatory) alternatives:
HTML:
<div class="row-flex">
Single
Larger title
Another really large title
</div>
CSS:
.row-flex {
display: flex;
}
.button {
flex-grow: 1; /* make the item grow proportionally to its original size */
/* default value is 0, the item does not grow */
/* a meaningful default for flexbox items positioning with */
/* justify-content: <value>; */
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
The following CSS declarations also work because all they do is override the default flex-grow: 0; to the (for the desired behavior required) flex-grow: 1;:
.button {
flex: auto;
...
}
which is a shorthand for:
.button {
flex: 1 1 auto;
...
}
which is a shorthand for:
.button {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
...
}
I have 3 buttons in a row which all vary in width. I want them to all gain width the same to fill the remaining width of the row, so the widest will still be wider than the others etc.
You can see below that what I've tried to do with flex has resulted in all the buttons being the same width. I know flex-grow can be used to proportionally grow each item, but I can't work out how to get them all to grow in relation to their original size.
You can see in the second row that the blue item is larger than the other two. I just want all three to expand from their current size equally to fill the row.
Thanks
.row-flex {
width: 100%;
display: flex;
flex-direction: row;
}
.button {
flex: 1;
display: inline-block;
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
<div class="row-flex">
Single
Larger title
Another really large title
</div>
<br/>
<div class="row">
Single
Larger title
Another really large title
</div>
Short Answer
Switch from flex: 1 to flex: auto.
Explanation
The flex-grow property factors in two key pieces of data:
The free space in the row / column where it is being used.
The value of the flex-basis property.
Distribution of Free Space
The flex-grow property distributes free space in the container among flex items in the same line.
If there is no free space, flex-grow has no effect.
If there is negative free space (i.e., the total length of flex items is greater than the length of the container), then flex-grow has no effect and flex-shrink comes into play.
The flex-basis factor
When flex-basis is 0, flex-grow ignores the size of the content in flex items and treats all space on the line as free space.
This is absolute sizing. All space on the line is distributed.
When flex-basis is auto, the size of the content in flex items is first deducted to determine the free space in each item. flex-grow then distributes the free space among items (based on each item's flex-grow value).
This is relative sizing. Only extra space on the line is distributed.
Here's an illustration from the spec:
Examples:
flex: 1 (absolute sizing)
This shorthand rule breaks down to: flex-grow: 1 / flex-shrink: 1 / flex-basis: 0
Applied to all flex items, this will make them equal length, regardless of content. (Note that in some cases an override of default minimum sizing will be necessary for this effect to occur.)
flex-grow: 1 (relative sizing)
This rule by itself will factor in both content size and available space, because the default value for flex-basis is auto.
flex: auto (relative sizing)
This shorthand factors in both content size and available space because it breaks down to:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
More variations here: 7.1.1. Basic Values of flex
additional keywords for search: difference between flex-basis auto 0 flex 1 auto
Not sure if this is entirely what you are after, but if you just set flex-grow:1 instead of flex:1;, I think that is your required result:
.row-flex {
width: 100%;
display: inline-flex;
flex-direction: row;
}
.button {
flex-grow: 1;
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
<div class="row-flex">
Single
Larger title
Another really large title
</div>
Using flex property you can set proportions:
.button {
display: inline-block;
padding: 10px;
color: #fff;
text-align: center;
}
.row {
display: flex;
}
.button--1 {
background: red;
flex: 1 1 auto;
}
.button--2 {
background: green;
flex: 2 1 auto;
}
.button--3 {
background: blue;
flex: 3 1 auto;
}
<br/>
<div class="row">
Single
Larger title
Another really large title
</div>
Minimalistic answer with (hopefully useful, explanatory) alternatives:
HTML:
<div class="row-flex">
Single
Larger title
Another really large title
</div>
CSS:
.row-flex {
display: flex;
}
.button {
flex-grow: 1; /* make the item grow proportionally to its original size */
/* default value is 0, the item does not grow */
/* a meaningful default for flexbox items positioning with */
/* justify-content: <value>; */
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
The following CSS declarations also work because all they do is override the default flex-grow: 0; to the (for the desired behavior required) flex-grow: 1;:
.button {
flex: auto;
...
}
which is a shorthand for:
.button {
flex: 1 1 auto;
...
}
which is a shorthand for:
.button {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
...
}
I have 3 buttons in a row which all vary in width. I want them to all gain width the same to fill the remaining width of the row, so the widest will still be wider than the others etc.
You can see below that what I've tried to do with flex has resulted in all the buttons being the same width. I know flex-grow can be used to proportionally grow each item, but I can't work out how to get them all to grow in relation to their original size.
You can see in the second row that the blue item is larger than the other two. I just want all three to expand from their current size equally to fill the row.
Thanks
.row-flex {
width: 100%;
display: flex;
flex-direction: row;
}
.button {
flex: 1;
display: inline-block;
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
<div class="row-flex">
Single
Larger title
Another really large title
</div>
<br/>
<div class="row">
Single
Larger title
Another really large title
</div>
Short Answer
Switch from flex: 1 to flex: auto.
Explanation
The flex-grow property factors in two key pieces of data:
The free space in the row / column where it is being used.
The value of the flex-basis property.
Distribution of Free Space
The flex-grow property distributes free space in the container among flex items in the same line.
If there is no free space, flex-grow has no effect.
If there is negative free space (i.e., the total length of flex items is greater than the length of the container), then flex-grow has no effect and flex-shrink comes into play.
The flex-basis factor
When flex-basis is 0, flex-grow ignores the size of the content in flex items and treats all space on the line as free space.
This is absolute sizing. All space on the line is distributed.
When flex-basis is auto, the size of the content in flex items is first deducted to determine the free space in each item. flex-grow then distributes the free space among items (based on each item's flex-grow value).
This is relative sizing. Only extra space on the line is distributed.
Here's an illustration from the spec:
Examples:
flex: 1 (absolute sizing)
This shorthand rule breaks down to: flex-grow: 1 / flex-shrink: 1 / flex-basis: 0
Applied to all flex items, this will make them equal length, regardless of content. (Note that in some cases an override of default minimum sizing will be necessary for this effect to occur.)
flex-grow: 1 (relative sizing)
This rule by itself will factor in both content size and available space, because the default value for flex-basis is auto.
flex: auto (relative sizing)
This shorthand factors in both content size and available space because it breaks down to:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
More variations here: 7.1.1. Basic Values of flex
additional keywords for search: difference between flex-basis auto 0 flex 1 auto
Not sure if this is entirely what you are after, but if you just set flex-grow:1 instead of flex:1;, I think that is your required result:
.row-flex {
width: 100%;
display: inline-flex;
flex-direction: row;
}
.button {
flex-grow: 1;
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
<div class="row-flex">
Single
Larger title
Another really large title
</div>
Using flex property you can set proportions:
.button {
display: inline-block;
padding: 10px;
color: #fff;
text-align: center;
}
.row {
display: flex;
}
.button--1 {
background: red;
flex: 1 1 auto;
}
.button--2 {
background: green;
flex: 2 1 auto;
}
.button--3 {
background: blue;
flex: 3 1 auto;
}
<br/>
<div class="row">
Single
Larger title
Another really large title
</div>
Minimalistic answer with (hopefully useful, explanatory) alternatives:
HTML:
<div class="row-flex">
Single
Larger title
Another really large title
</div>
CSS:
.row-flex {
display: flex;
}
.button {
flex-grow: 1; /* make the item grow proportionally to its original size */
/* default value is 0, the item does not grow */
/* a meaningful default for flexbox items positioning with */
/* justify-content: <value>; */
padding: 10px;
color: #fff;
text-align: center;
}
.button--1 {
background: red
}
.button--2 {
background: green;
}
.button--3 {
background: blue;
}
The following CSS declarations also work because all they do is override the default flex-grow: 0; to the (for the desired behavior required) flex-grow: 1;:
.button {
flex: auto;
...
}
which is a shorthand for:
.button {
flex: 1 1 auto;
...
}
which is a shorthand for:
.button {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
...
}
I'm trying to make a chat layout. So i have 3 divs, activeUSer - top, messages middle (has to fill the space between 1 and 3), actions - bottom
Now, I've put flex-direction row. and it works fine. I needed the bottom div to grow if the input grows (if you have 2 or more lines of writing)
It worked ok untill I added display:flex to the Actions div (bottom). I needed another flex layout for input and buttons. Now it does not care for the padding i've set on the last div
Here is my codepen https://codepen.io/capraruioan/pen/XKWxrV
#content {
height: 300px;
display: flex;
flex-direction: column;
}
.activeUser {
height: 66px;
background-color: yellow;
}
.Messages {
flex: 1 1 100%;
}
.Actions {
flex-grow: 1;
display: flex;
padding-top: 2px;
padding-bottom: 20px;
}
.aa { //the inputbox
border: 1px solid black;
min-height: 10px
}
fixed it by letting display default on the 3rd div and placing a div with display flex inside
(I'm using Chrome v.39+)
I'm trying to use the flex-wrap property to stack child divs both horizontally and vertically, but I'm seeing some very strange behaviors. For example, if there's 3 child divs and the last is given a width of 100% (causing it to wrap) there will be unwanted gaps introduced.
Sometimes I can force the first 2 divs to honor align-items: stretch by giving them height: 100% or height: calc(100% - 1px), other times they won't stretch passed the mysterious gap, and sometimes they'll even disappear all together if I try to force them to stretch.
Here's a simplified example of the problem. They grey shouldn't be visible.
Why are these gaps appearing in flex-wrapped divs and how can I prevent them?
The gray area is still visible at the bottom because you set a height on the parent container.
If you don't want to see that gray area, remove the height from the container and add a fixed height that you require on one of the elements in the first row
DEMO
.a {
width: 300px;
display: flex;
flex-wrap: wrap;
position: relative;
top: 100px;
left: 200px;
background-color: #999;
}
.b {
height: 150px;
background-color: #00ff00;
}
.c {
background-color: #0000ff;
}
.d {
background-color: #ff0000;
}
.b {
flex-grow: 1;
flex-shrink: 0;
}
.c {
width: 5px;
flex-shrink: 0;
}
.d {
width: 100%;
height: 10px;
flex-shrink: 0;
}
<div class='a'>
<div class='b'></div>
<div class='c'></div>
<div class='d'></div>
</div>
Note: If you want to avoid fixed dimensions - just remove the height:10px from the red div.
This will ensure that there are no gaps and that each row has equal height
DEMO