问题
I got this simple setup with 3 elements in a flex-box. They are justified space-between. The middle .center element is set width 100%. For some reason the children elements (links) wrap, no matter how wide the window is.
What is the mechanism behind the result being that the links are being wrapped to the next line? There is enough space. Why isn't the .center div taking 100% of the left over space so they don't wrap. And how do I prevent this wrapping?
PS: I want the .center div to take 100% of the space in between.
<div class="header">
<h1>Title</h1>
<div class="center">
<h1>
TEST TEXT
</h1>
</div>
<div class="nav">
<a>A Link</a>
<a>Another Link</a>
<a>A Third Link</a>
</div>
.header {
background: #ccc;
display: flex;
justify-content: space-between;
}
.nav{
width: fit-content;
}
.center{
width:100%;
background: lightblue;
text-align: center;
}
div a{
background: tomato;
}
See here: http://jsfiddle.net/vsx239v1/
回答1:
To understand why your nav elements are wrapping, you need to understand how flexbox works. I am going to explain this briefly with simple words but below you will find a reference with a complete and precise explanation.
Initially, you have set one item to take 100% of width and you kept everything else as default values. The important values used here are:
flex-wrap:nowrap
(by default the flex items will not wrap)flex-shrink:1
(by default the flex items will shrink)min-width:auto
(by default the flex items will not shrink past their minimum content size)flex-grow:0
(by default the flex items will not grow)
In your case it's clear that we have overflow since one element is set to width:100%
and the other to auto BUT the flexbox mechanism will shrink your element and will distribute the negative free space1 to the flex items in order to avoid the overflow.
In your case the first element h1
can no more shrink since its width
is equal to its min-content so only your .center
element and the nav will shrink and this will happen whataver the size of the browser is because we will always have negative free space since the .center
element is set to width:100%
.
If for example you set flex-shrink:0
to the nav element you won't have wrapping because you disable the shrink for this one and all the negative free space will be added to the .center
element (this can be a fix, but not the best one)
.header {
background: #ccc;
display: flex;
justify-content: space-between;
}
h1 {
font-size:11px;
}
.center{
width:100%;
background: lightblue;
text-align: center;
}
.nav {
flex-shrink:0;
}
div a{
background: tomato;
}
<div class="header">
<h1>Title</h1>
<div class="center">
<h1>
TEST TEXT
</h1>
</div>
<div class="nav">
<a>A Link</a>
<a>Another Link</a>
<a>A Third Link</a>
</div>
</div>
If you disable the shrink factor for all the elements we will have an overflow because the negative free space will not be distributed:
.header {
background: #ccc;
display: flex;
justify-content: space-between;
}
h1 {
font-size:11px;
}
.center{
width:100%;
background: lightblue;
text-align: center;
flex-shrink:0;
}
.nav {
flex-shrink:0;
}
div a{
background: tomato;
}
<div class="header">
<h1>Title</h1>
<div class="center">
<h1>
TEST TEXT
</h1>
</div>
<div class="nav">
<a>A Link</a>
<a>Another Link</a>
<a>A Third Link</a>
</div>
</div>
If you set flex-wrap:wrap
on the container we will no more consider negative free space and shrinking as if there is no enough space the elements will wrap:
.header {
background: #ccc;
display: flex;
justify-content: space-between;
flex-wrap:wrap;
}
h1 {
font-size:11px;
}
.center{
width:100%;
background: lightblue;
text-align: center;
}
div a{
background: tomato;
}
<div class="header">
<h1>Title</h1>
<div class="center">
<h1>
TEST TEXT
</h1>
</div>
<div class="nav">
<a>A Link</a>
<a>Another Link</a>
<a>A Third Link</a>
</div>
</div>
In order to fix all this you need to avoid having negative free space and make the total width to not exceed the container width. Instead of using width:100%
you can consider flex-grow
property that will allow an item to grow in order to fill the free space.
.header {
background: #ccc;
display: flex;
justify-content: space-between;
}
h1 {
font-size:11px;
}
.center{
flex-grow:1;
background: lightblue;
text-align: center;
}
div a{
background: tomato;
}
<div class="header">
<h1>Title</h1>
<div class="center">
<h1>
TEST TEXT
</h1>
</div>
<div class="nav">
<a>A Link</a>
<a>Another Link</a>
<a>A Third Link</a>
</div>
</div>
Here is a good link to better understand the flexbox algorithm considering all the properties : https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Controlling_Ratios_of_Flex_Items_Along_the_Main_Ax
(1) Negative free space: We have negative free space when the natural size of the items adds up to larger than the available space in the flex container.
回答2:
You need to use flex-grow: 1
instead of width: 100%
.
Also width: fit-content;
is useless here:
.header {
background: #ccc;
display: flex;
justify-content: space-between;
}
.center{
flex-grow: 1;
background: lightblue;
text-align: center;
}
div a{
background: tomato;
}
<div class="header">
<h1>Title</h1>
<div class="center">
<h1>
TEST TEXT
</h1>
</div>
<div class="nav">
<a>A Link</a>
<a>Another Link</a>
<a>A Third Link</a>
</div>
回答3:
Change 100% to auto;
.center{
width:auto;
background: lightblue;
text-align: center;
}
CSS will always follow your 100% width, making the title and the link adjust, thus the wrapping.
来源:https://stackoverflow.com/questions/50458282/the-unpredictable-wrapping-habits-of-css