Uniform width using flex and border
I am using box-sizing: border-box;
with variable thickness border
within flexbox. I want the items inside the flexbox to have equal width, but it calculates the width
item without borders.
Here's an example: width
my container 100px
, so every item should be 20px
; however they are 19.2px
(x4) and 23.2px
.
.container {
display: flex;
flex-direction: row;
align-items: center;
width: 100px;
}
.container .block {
height: 28px;
flex: 1;
border: 1px solid black;
box-sizing: border-box;
}
.container .block.selected {
border: 3px solid blue;
}
<div class="container">
<span class="block">0</span>
<span class="block">1</span>
<span class="block selected">2</span>
<span class="block">3</span>
<span class="block">4</span>
</div>
source to share
box-sizing: border-box
used to change the default CSS field model used for calculations width
and height
elements.
So it would be like this:
-
total width
=border
+padding
+content width
and
-
total height
=border
+padding
+content height
But this does not happen in flex-grow
, but inflex-basis
Here is a nice tutorial about flexbox
So you can use flex:0 20%
instead flex:1
,
.container {
display: flex;
flex-direction: row;
align-items: center;
width: 100px;
}
.container .block {
height: 28px;
flex: 0 20%;
border: 1px solid black;
box-sizing: border-box;
}
.container .block.selected {
border: 3px solid blue;
}
<div class="container">
<span class="block">0</span>
<span class="block">1</span>
<span class="block selected">2</span>
<span class="block">3</span>
<span class="block">4</span>
</div>
Note: if you have more elements than 5 then you can use calc()
like this flex: 0 calc(100%/8)
where 8 is the number of elements you will have
Fragment with a lot of elements
.container {
display: flex;
flex-direction: row;
align-items: center;
width: 100px;
}
.container .block {
height: 28px;
flex: 0 calc(100%/8);
border: 1px solid black;
box-sizing: border-box;
}
.container .block.selected {
border: 3px solid blue;
}
<div class="container">
<span class="block">0</span>
<span class="block">1</span>
<span class="block selected">2</span>
<span class="block">3</span>
<span class="block">4</span>
<span class="block">5</span>
<span class="block">6</span>
<span class="block">7</span>
</div>
source to share
The property does not set the width or height of flex items. The challenge is to distribute the free space in the container between flex items. flex-grow
You have all the elements set to , which is shorthand for: flex: 1
-
flex-grow: 1
-
flex-shrink: 1
-
flex-basis: 0
This distributes the free space on the line evenly between the elements.
BUT borders (and additions) are counted separately.
flex-grow
doesn't care about because it applies to > and which, as mentioned earlier, are not functions . box-sizing: border-box
box-sizing
width
height
flex-grow
Use a property instead , which is equivalent (in line is the direction container) and will respect : flex-basis
width
box-sizing
flex: 0 0 20%;
.container {
display: flex;
flex-direction: row;
align-items: center;
width: 100px;
}
.container .block {
height: 28px;
flex: 0 0 20%; /* adjustment */
border: 1px solid black;
box-sizing: border-box;
}
.container .block.selected {
border: 3px solid blue;
}
<div class="container">
<span class="block">0</span>
<span class="block">1</span>
<span class="block selected">2</span>
<span class="block">3</span>
<span class="block">4</span>
</div>
source to share
Instead of setting the flex to one unit, you can set the flex to the base to 20% and then the width will be divided equally:
.container {
display: flex;
flex-direction: row;
align-items: center;
width: 100px;
}
.container .block {
height: 28px;
flex-basis: 20%;
border: 1px solid black;
box-sizing: border-box;
}
.container .block.selected {
border: 3px solid blue;
}
<div class="container">
<span class="block">0</span>
<span class="block">1</span>
<span class="block selected">2</span>
<span class="block">3</span>
<span class="block">4</span>
</div>
source to share
One way would be to install the add- 2px
on .block
and uninstall it for.selected
.container {
display: flex;
flex-direction: row;
align-items: center;
width: 100px;
}
.container .block {
height: 28px;
flex: 1;
border: 1px solid black;
box-sizing: border-box;
padding: 2px;
}
.container .block.selected {
border: 3px solid blue;
padding: 0px;
}
<div class="container">
<span class="block">0</span>
<span class="block">1</span>
<span class="block selected">2</span>
<span class="block">3</span>
<span class="block">4</span>
</div>
source to share
Your problem here is flex: 1;
to change it to flex: 1 0 20%;
even for more items. there is no need to calculate the width using calc
as mentioned earlier.
also just change this:
.container .block {
height: 28px;
flex: 1;
border: 1px solid black;
box-sizing: border-box;
}
in
.container .block {
height: 28px;
flex: 1 0 20%;
border: 1px solid black;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
source to share