Using Flexbox with padding in the inner items
The flex-grow
property is not designed for precision sizing of flex items. It's job is to distribute space in the container among flex items. So flex-grow
is not the best tool for this job.
Instead, use flex-basis
, which is the equivalent of width
or height
(depending on flex-direction
) in a flex container.
Then add box-sizing: border-box
to integrate the padding into the flex item's width.
revised fiddle demo
<div style="display: flex;"> <div style="flex-basis: 60%; padding: 4rem ; background-color: red; box-sizing: border-box;"> </div> <div style="flex-basis: 40%; background-color: green;"> </div></div>
How to make flex-grow ignore padding?
How to make
flex-grow
ignorepadding
?
flex-grow
cannot ignore padding
:
flex-grow
consumes free space.padding
occupies space.So
flex-grow
must factor inpadding
in order to work properly.
Here's a workaround that may be useful to you:
.flexbox {
display: flex;
max-width: 1241px;
height: 30px;
}
label {
flex: 5 1 0;
background-color: cyan;
}
#input {
flex: 13 1 0;
height: 100%;
}
input {
height: 100%;
width: 100%;
padding-left: 25px;
background-color: yellow;
border: none;
}
div:last-child {
flex: 6 1 0;
background-color: red;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-size: 14px;
}
<div class="flexbox">
<label>width must = 258.54px</label>
<div id="input"><input type="text" value="width must = 672.20px"></div>
<div>width must = 310.25px</div>
</div>
Padding of one flex item influence the rest of flex items
i am added align-items:center;
. because, default align-items:
is stretch
.footer__form { flex-basis: 49%; display: flex; justify-content: space-between; flex-direction: row; align-items:center;} .footer__form--email { flex: 0 0 65%; padding: 1.5rem 1.5rem; }
.footer__form--email--submit { flex: 0 0 30%; font-weight: 700;
}
<div class="footer__form"> <input type="email" class="footer__form--email" placeholder="enter your email for updates"> <input type="submit" class="footer__form--submit u-uppercase-text" value="sign up"></div>
How to get flexbox to include padding in calculations?
The solution:
Set margin
on the child element instead of padding
on your flex
item.
.Row{ display:flex;}.Item{ display:flex; flex:1; flex-direction:column;}.Item > div{ background:#7ae; margin:0 10px 10px 0;}.Flx2{ flex:2;}
<div class="Row"> <div class="Item"> <div>1A</div> </div> <div class="Item"> <div>1B</div> </div> <div class="Item Flx2"> <div>1C</div> </div></div>
<div class="Row"> <div class="Item"> <div>2A</div> </div> <div class="Item"> <div>2B</div> </div></div>
Why does child padding expand parent width?
A complex case of shrink-to-fit behavior. All your rows are flex items so their width depend on their content. Now the complex part is that you are making the child having width:100%
which means 100% of the parent width so we have a cycle here.
In such case the browser will do the following:
- ignore the
width:100%
(consider it as auto) - find the width of the child using other properties
- set the width of the parent based on (2)
- get back to the resolve
width:100%
based on the width found in (3) - the width of child may change but not the one of the parent.
If one child is 100% then logically both cannot fit into one line and each one will be on its own line.
Here is a 2 steps illustration to understand what is happening:
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
color: #C0C0C0;
background-color: #202020;
display: flex;
flex-direction: column;
align-items: center;
}
* {
box-sizing: border-box;
}
.col {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
background-color: gray
}
.wrap {
flex-wrap: wrap;
}
.align-center {
align-items: center;
}
.justify-center {
justify-content: center;
}
.gap {
gap: 20px;
}
input {
background-color:#202020 ;
border: 1px solid #C0C0C0 ;
border-radius: 5px;
padding: 12px 20px;
margin: 8px 0;
box-sizing: border-box;
}
.inputContainer {
max-width: 300px;
width: 100%;
}
.inputContainer > * {
width: 100%;
}
<form class="col gap align-center" style="width: 90vw" action="">
<div class="row wrap gap justify-center">
<div class="col inputContainer" style="width:auto">
<label>expands:</label>
<input />
</div>
<div class="col inputContainer" style="width:auto">
<label>parent:</label>
<input />
</div>
</div>
</form>
<hr>
<form class="col gap align-center" style="width: 90vw" action="">
<div class="row wrap gap justify-center">
<div class="col inputContainer" >
<label>expands:</label>
<input />
</div>
<div class="col inputContainer">
<label>parent:</label>
<input />
</div>
</div>
</form>
Flexbox item widths are affected by padding
1 option you have is to set flex-basis: 33.33%
or a number relative to the amount of children you have. I'm not sure if there is a way to do it dynamically.
Flex-Grow leading to different widths depending on the markup
Simply keep the same structure and wrap all the input in div element to get the same result:
* {
box-sizing: border-box;
}
div {
width: 400px;
}
.form-input {
padding: 4px;
border: 1px solid #565656;
}
.form-input-list {
list-style-type: none;
width: 100%;
padding-left: 0;
}
.form-input-item {
display: flex;
align-items: center;
}
.form-label {
flex-basis: 0;
flex-grow: 1;
background-color: yellow;
}
.form-input,
.form-input-group {
flex-basis: 0;
flex-grow: 1.5;
}
.form-input-group {
display: flex;
}
.form-input-group-item {
flex-basis: 0;
flex-grow: 1;
}
<div>
<form>
<ul class="form-input-list">
<li class="form-input-item">
<label class="form-label">First Name</label>
<div class="form-input-group">
<input type="text" class="form-input" />
</div>
</li>
<li class="form-input-item">
<label class="form-label">Last Name</label>
<div class="form-input-group">
<input type="text" class="form-input" />
</div>
</li>
<li class="form-input-item">
<label class="form-label">Phone</label>
<div class="form-input-group">
<select class="form-input-group-item form-input">
<option>+49</option>
</select>
<input class="form-input-group-item form-input" type="text" />
</div>
</li>
</ul>
</form>
</div>
How does flex-shrink factor in padding and border-box?
Flexbox defines this as
For every unfrozen item on the line, multiply its flex shrink factor
by its inner flex base size, and note this as its scaled flex
shrink factor. Find the ratio of the item’s scaled flex shrink
factor to the sum of the scaled flex shrink factors of all
unfrozen items on the line. Set the item’s target main size to
its flex base size minus a fraction of the absolute value of the
remaining free space proportional to the ratio.
Simplifying, frozen flex items are those which can't or don't have to be flexed anymore. I will assume no min-width
restrictions and non-zero flex shrink factors. This way all flex items are initially unfrozen and they all become frozen after only one iteration of the flex loop.
The inner flex base size depends on the value of box-sizing
, defined by CSS2UI as
content-box
: The specified width and height (and respective min/max properties) apply to the width and height respectively of the
content box of the element. The padding and border of the element are
laid out and drawn outside the specified width and height.
border-box
: Length and percentages values for width and height (and respective min/max properties) on this element determine the
border box of the element. That is, any padding or border specified on
the element is laid out and drawn inside this specifiedwidth
andheight
. The content width and height are calculated by
subtracting the border and padding widths of the respective sides from
the specified width and height properties. [...] Used values, as
exposed for instance through getComputedStyle(), also refer to the
border box.
Basically, that means that sizes (widths, flex bases) have an inner an an outer variant. The inner size includes only the content, the outer one also includes paddings and border widths. The length specified in the stylesheet will be used as the inner size in case of box-sizing: content-box
, or as the outer one in case of box-sizing: border-box
. The other can be calculated by adding or subtracting border and padding widths.
Neglecting lots of details, the algorithm would be something like
let sumScaledShrinkFactors = 0,
remainingFreeSpace = flexContainer.innerMainSize;
for (let item of flexItems) {
remainingFreeSpace -= item.outerFlexBasis;
item.scaledShrinkFactor = item.innerFlexBasis * item.flexShrinkFactor;
sumScaledShrinkFactors += item.scaledShrinkFactor;
}
for (let item of flexItems) {
let ratio = item.scaledShrinkFactor / sumScaledShrinkFactors;
item.innerWidth = item.innerFlexBasis + ratio * remainingFreeSpace;
}
With no paddings, it's as you explain
(width)
innerW │ padd │ outerW
───────┼──────┼───────
300px * (1 + 2 / 1000px * -200px) = 180px │ 0px │ 180px
200px * (1 + 1 / 1000px * -200px) = 160px │ 0px │ 160px
100px * (1 + 2 / 1000px * -200px) = 60px │ 0px │ 60px
───────┼──────┼───────
400px │ 0px │ 400px
With 10px
horizontal paddings, the available space is reduced by 3 * 2 * 10px = 60px
, so now it's -260px
.
(width)
innerW │ padd │ outerW
───────┼──────┼───────
300px * (1 + 2 / 1000px * -260px) = 144px │ 20px │ 164px
200px * (1 + 1 / 1000px * -260px) = 148px │ 20px │ 168px
100px * (1 + 2 / 1000px * -260px) = 48px │ 20px │ 68px
───────┼──────┼───────
340px │ 60px │ 400px
When you use box-sizing: border-box
, the specified flex bases are the outer ones, so the paddings are subtracted from them to calculate the inner ones, which are 280px
, 180px
, 80px
. Then the sum of the scaled flex shrink factors becomes 2*280px + 180px + 2*80px = 900px
. The available space is like in the case with no padding, because the outer flex bases are the same. Note the width
retrieved by getComputedStyle
will now be the outer one, so paddings are added back at the end.
(width)
innerW │ padd │ outerW
────────┼──────┼────────
280px * (1 + 2 / 900px * -200px) ≈ 155.6px │ 20px │ 175.6px
180px * (1 + 1 / 900px * -200px) = 140.0px │ 20px │ 160.0px
80px * (1 + 2 / 900px * -200px) ≈ 44.4px │ 20px │ 64.4px
────────┼──────┼────────
340.0px │ 60px │ 400.0px
Related Topics
Number Input - Always Show Spin Buttons
Will Targeting Ie8 with Conditional Comments Work
How to Create More Than One Repository for Github Pages
Complete List of Reasons Why a CSS File Might Not Be Working
Setting The Height of a Select in Ie
Make Flex Container Take Width of Content, Not Width 100%
Reset Particular Input Element in a HTML Form
Word Wrap a Link So It Doesn't Overflow Its Parent Div Width
Schema.Org/Microdata Markup for List of Recent Posts Without Providing "Author"/"Publisher"
How to Replace Radio Buttons with Images
Favicon: .Ico or .Png/Correct Tags
How to Detect HTML5 Audio Mp3 Support
CSS Position Element "Fixed" Inside Scrolling Container
Encoding Ffmpeg to Mpeg-Dash - or Webm with Keyframe Clusters - for Mediasource API