According to flex-basis
MDN documentation the flex-basis
property calculates the size of a flex item related to the content box, unless a different option is defined by the box-sizing
CSS property. But I didn't get the desired result neither in current Chrome nor in IE11.
I have written 2 examples:
.horizontal-layout {
display: flex;
flex-direction: row;
}
header > span {
flex: 1 1 100%;
}
header > .button {
background-color: grey;
}
header > .app-name {
background-color: orange;
}
header#with-border-padding > span {
box-sizing: border-box; /* this is not useful at all */
}
header#with-border-padding > .button {
border: 1px solid black;
padding-left: 5px;
}
<header class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
<header id="with-border-padding" class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
<header>
with 3 <span>
tags each one having a flex: 1 1 100%
(flex-basis
is 100%). So every span
is given a third part of the header
.span
has some border and some padding. I thought that flex-grow
would make same result as first example but it didn't. Then I saw the flex-basis
MDN documentation and understood that I had to set box-sizing: border-box;
to the flex items so that the flex-basis
was related to the border-box
. But it didn't either! Anyone knows why?
So thanks if someone can clarify about second example question.
In my code you can easily compare the sizes given to the <span>
tags between both examples.
The main size of a flex item is the size it has in the main dimension. If you are working in a row — in English — then the main size is the width. In a column in English, the main size is the height. Items also have a minimum and maximum main size as defined by their min-width or min-height on the main dimension.
The flex-basis CSS property sets the initial main size of a flex item. It sets the size of the content box unless otherwise set with box-sizing .
By default, if you have a width set and did not declare a flex basis value, width will function normally on that element. There is no difference between how flex-basis: will function on your element and how width: will function on your element. Width will even obey flex-shrink when using Flexbox.
On the block axis ( flex-direction: column ), flex-basis takes the height of the flex-items into account, instead of their width. In this case, the flex-basis value prevails over the height value, just like with the width value on the inline axis.
So it's clear that the columns across the two rows don't line up:
.horizontal-layout {
display: flex;
flex-direction: row;
}
header > span {
flex: 1 1 100%;
}
header > .button {
background-color: grey;
}
header > .app-name {
background-color: orange;
}
header#with-border-padding > span {
box-sizing: border-box;
}
header#with-border-padding > .button {
border: 1px solid black;
padding-left: 5px;
}
<header class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
<header id="with-border-padding" class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
There are several ways to tackle this problem, and they involve flex-basis
and box-sizing
, and also flex-shrink
and padding
.
For example, if you disable flex-shrink
, the alignment problem is gone.
.horizontal-layout {
display: flex;
flex-direction: row;
}
header > span {
flex: 1 0 100%; /* adjustment */
}
header > .button {
background-color: grey;
}
header > .app-name {
background-color: orange;
}
header#with-border-padding > span {
box-sizing: border-box;
}
header#with-border-padding > .button {
border: 1px solid black;
padding-left: 5px;
}
<header class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
<header id="with-border-padding" class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
Similarly, if you remove the padding, the alignment problem is also fixed.
.horizontal-layout {
display: flex;
flex-direction: row;
}
header > span {
flex: 1 1 100%;
}
header > .button {
background-color: grey;
}
header > .app-name {
background-color: orange;
}
header#with-border-padding > span {
box-sizing: border-box;
}
header#with-border-padding > .button {
border: 1px solid black;
/* padding-left: 5px; */ /* adjustment */
}
<header class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
<header id="with-border-padding" class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
The way flex-basis
, flex-shrink
, padding
and border-box
interact to establish box sizes involves some relatively complex calculations. They are explained here:
A simple solution to the problem is:
header > span { flex: 1 0 7px; }
.horizontal-layout {
display: flex;
flex-direction: row;
}
header > span {
flex: 1 0 7px; /* adjustment */
}
header > .button {
background-color: grey;
}
header > .app-name {
background-color: orange;
}
header#with-border-padding > span {
box-sizing: border-box;
}
header#with-border-padding > .button {
border: 1px solid black;
padding-left: 5px;
}
<header class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
<header id="with-border-padding" class="horizontal-layout">
<span class="button">A</span>
<span class="app-name">B</span>
<span class="button">C</span>
</header>
With flex-grow: 1
defined in the flex
shorthand, there's no need for flex-basis
to be 100%. Each item will receive an equal share of free space on the line. However, flex-basis
needs to be at least big enough to absorb the padding
and border
coming from box-sizing: border-box
(in this case 7px). The columns are now aligned across rows.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With