flex-grow not sizing flex items as expected
Short Analysis
The problem is that rows 1-3 have two horizontal margins and row 4 only has one.
With horizontal margins at 10px each, row 4 has 10px more free space than the other rows. This throws off the alignment of the columns.
Because flex-grow
applies only to free space, and is heavily influenced by content and margins, it's not the most secure way to size flex items.
Try flex-basis
instead. Add this to your code:
.button { flex-basis: 33.33%; }
#number0 { flex-basis: calc(66.67% + 10px); }
* { box-sizing: border-box; }
.numbers { display: flex; flex-direction: column;}
.row { display: flex; flex-direction: row; flex-grow: 1; justify-content: space-between;}
.button { display: flex; flex-basis: 33.33%; justify-content: center; align-items: center; margin: 5px; border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.2); cursor: pointer;}
#number0 { flex-basis: calc(66.67% + 10px); }* { box-sizing: border-box; }
<div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div></div>
Inconsistency between flex-grow and width on flex items
You need to set the flex-basis property on your flex-items to 0%
#flex-item-1 {
flex-basis: 0%;
flex-grow: 3;
background-color: tomato;
/* width: 75%; */
}
#flex-item-2 {
flex-basis: 0%;
flex-grow: 1;
background-color: pink;
/* width: 25%; */
}
It specifies the initial size of the flex item, before any available space is distributed according to the flex factors. When omitted from the flex shorthand, its specified value is the length zero. Source: mdn
Stackblitz example
flex grow not working as described
You need to add flex-grow:1;
to .d1 . Because flex-grow determines how the remaining space is divided between flex-items and how much each item receives.
So if you don't set flex-grow for some items, they won't get that space, and you won't get elements' widths as you expect.
.d1{
flex-grow: 1;
}
.parent { display: flex; border: 1px solid rgba(0, 0, 0, .5); height: 300px; width: 300px; flex-flow: row wrap; justify-content: center; align-items: center;
}
.parent div { width: 50px; height: 50px; background-color: blue; margin: 1px; color: white; text-align: center; line-height: 50px;}
.d1 { flex-grow: 1;}
.d2 { flex-grow: 3;}
<div class="parent"> <div class="d1">1</div> <div class="d2">2</div>
</div>
Do not fill the width of growable flex containers
I think it would be better to use css grid instead:
* {
box-sizing: border-box;
margin: 0;
padding:0;
}
article {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
width: 800px;
padding: 10px;
border: 1px solid blue;
}
section {
padding: 10px;
border: 1px solid black;
}
Can I shrink flexbox items into same size when flex items are bigger than the flex container?
I would use display: grid
instead of display: flex
to achieve this. Here is an example:
.flex-container { font-size: 12px; display: grid; grid-template-columns: 1fr; grid-template-rows: repeat(2, minmax(minmax(0, auto), 50%)); width: 200px; height: 500px; border: 1px solid #dadfe3;}
.flex-item { min-height: 0; overflow: auto; margin: 0 20px;}
.flex-item div { margin: 4px 0; background-color: #f0f9ff; color: #2f88ff;}
<body> <div class="flex-container"> <div class="flex-item"> <input type="text" placeholder="filter 1"> <div>item content 1</div> <div>item content 2</div> <div>item content 3</div> <div>item content 4</div> <div>item content 5</div> <div>item content 6</div> </div> <div class="flex-item"> <input type="text" placeholder="filter 2"> <div>item 1</div> <div>item 2</div> <div>item 3</div> <div>item 4</div> <div>item 5</div> <div>item 6</div> <div>item 7</div> <div>item 8</div> <div>item 9</div> <div>item 10</div> <div>item 11</div> <div>item 12</div> <div>item 13</div> <div>item 14</div> <div>item 15</div> </div> </div></body>
Flex-grow with width property on element
Simply because the flex-grow
will make the element to consume the free space. In your case the first element has 100px
of width and the other one is having width equal to its content so the free space is (width of container - 100px - content of box2)
. This free space will be split equally and added to both element and it's logical that the first one will be bigger since initially it was already bigger.
In your example, the second element is about 29px
and if we fix the width of the container to 600px
for example, we will have a free space equal to 471px
so both elements will end with 335.5px
and 264.5px
of width.
.wrapper { display: flex; width:600px;}
.box1 { background: red; width: 100px; flex-grow: 1;}
.box2 { background: green; flex-grow: 1;}
<div class="wrapper"> <div class="box1">One</div> <div class="box2">Two</div></div>
Make flex-grow expand items based on their original size
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
How to prevent content from re-sizing a flex item?
When you tell a flex item to flex: 3
(Item 6) or flex: 1
(Items 5 & 7), here's how that shorthand property breaks down:
flex: ? = <flex-grow>, <flex-shrink>, <flex-basis>
flex: 3 = flex-grow: 3, flex-shrink: 1, flex-basis: 0
flex: 1 = flex-grow: 1, flex-shrink: 1, flex-basis: 0
In both cases, the flex-shrink
factor is 1, meaning the flex item is allowed to shrink proportionally.
To prevent the flex items from shrinking, which may be causing the misalignment, I would change the flex-shrink
to 0.
Instead of flex: 3
and flex: 1
try:
flex: 3 0 0;
flex: 1 0 0;
More details in the flexbox spec: 7.1.1. Basic Values of flex
But you may have another problem. You wrote:
Note that items 5 and 7 are setup the same way in css, with
flex
values of1
. I.e. item 6 is 3 times the height of items 5 and 7. As such, when item 6 resizes, the 3:1 ratio is maintained.
This is not how the flex-grow
property works.
By applying flex-grow: 3
to a flex item you are telling it to consume three times more available space than flex items with flex-grow: 1
. This does not necessarily mean Item 6 will be three times the size of Items 5 and 7.
Learn more about how flex-grow
works here: flex-grow not sizing flex items as expected
As an alternative sizing method, you may want to use the flex-basis
property. Try flex: 0 0 60%
on Item 6, and flex: 0 0 20%
on Items 5 and 7.
Related Topics
Change Color of Png Image Via Css
A Space Between Inline-Block List Items
How to Create a Circle With Links on Border Side
How to Add a Browser Tab Icon (Favicon) For a Website
Using External Images For CSS Custom Cursors
How to Make Blinking/Flashing Text With CSS 3
Html/Css Triangle With Pseudo Elements
How to Change the Height of a ≪Br≫
How to Wrap Text Around an Image Using Html/Css
Twitter Bootstrap 3, Vertically Center Content
Difference Between HTML Div and Span Elements
How to Style Even and Odd Elements
Several Elements With the Same Id Responding to One CSS Id Selector
Resize Image Proportionally With Css
How to Target a Specific Column or Row in CSS Grid Layout
Is There an Equivalent to Background-Size: Cover and Contain For Image Elements