So I have this:
.menu {
display: flex;
align-items: center;
justify-content: center;
/* flex-wrap: wrap; → I want this only when the children reach their min-width, to avoid horizontal scrolling */
}
.menu-title {
flex-shrink: 0;
}
.menu-item {
flex: 0 1 auto;
min-width: 10rem;
}
.menu-link {
padding: 0 1rem;
}
/* Demo purpose */
html,
body {
margin: 0;
padding: 0;
}
.menu {
margin: 2rem;
}
.menu-title {
margin-right: 1rem;
}
.menu-link {
display: flex;
position: relative;
text-decoration: none;
align-items: center;
}
.menu-icon {
display: block;
width: 2em;
height: 2em;
flex-shrink: 0;
margin-right: 0.5em;
background-color: #eee;
}
<div class="menu">
<div class="menu-title">Menu:</div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">A menu entry</span></a></div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">A very very very very long menu entry that should be on multiple lines</span></a></div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">A quite long menu entry</span></a></div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">A menu entry that is a bit longer</span></a></div>
</div>
<div class="menu">
<div class="menu-title">Menu:</div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">A two items menu entry</span></a></div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">Lorem ispum would have done the job at some point</span></a></div>
</div>
<div class="menu">
<div class="menu-title">Menu:</div>
<div class="menu-item"><a class="menu-link" href=""><span class="menu-icon"></span><span class="menu-text">A menu entry that is… you got it</span></a></div>
</div>
I want flex items to be exactly how they behave right now: only one line, shrink when they need, so the text goes on 2 lines, and grow when they can till their normal 'inline' width.
But they have a min-width, which create an horizontal scrolling at a point. And at this point, I'd like the last one to go on a new line: I want the wrap behavior, but not before they reach their min-width because I want them to shrink before.
The only way I managed to make it work, is by adding a wrap on .menu and allow items to grow, but when there's only one item, the render is not right (I still want the max width to be content width).
https://jsfiddle.net/joanva/9zgn3hcm/30/
(initial: https://jsfiddle.net/joanva/9zgn3hcm/)
Gotcha!
Setting .menu to wrap, and allowing items to grow + adding max-width: fit-content; makes it.
Intrinsic size is kinda cutting edge but graceful degradation ftw.
https://jsfiddle.net/joanva/9zgn3hcm/33/
What you're describing is a perfect use-case for grid.
The css would look something like this:
.menu {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
grid-gap: 1rem;
}
This sets up your grid so that it will attempt to 'auto-fit' the columns, stretching them between evenly spaced (1fr) and your minimum column width (10rem). If it can't fit the content on one row because they would go below the min-width, it will instead move the excess onto a new row.
Here is a jsfiddle example. You can try manually adding a few extra menu-items and see what happens: https://jsfiddle.net/547hq0Lb/4/
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