I have three block elements that I'm laying out with CSS Flexbox. (In my case, they happen to be two <select>s
on either side of a <div>ider
element; I'm building a List Builder control.)
What I want is:
Flexbox does a wonderful job of all of these points, except for the last requirement. I can't force all of the elements to wrap if there's less than enough space to have all of them on one line.
I'm using a fairly straightforward flexbox setup to achieve the layout:
.container {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
}
select {
flex-basis: 10em;
flex-grow: 1;
}
.divider {
flex-basis: 3em;
flex-grow: 0;
text-align: center;
}
The problem with this is that, if the container width is set to any amount that's wide enough for one select plus the divider, it will wrap the end select, but not the divider. I'll get a select plus a divider on one line, which looks ugly.
This fiddle illustrates the issue:
http://jsfiddle.net/5s0yf74w/1/
Is it possible to achieve my desired result by tweaking the CSS while retaining the general flexbox layout?
You could use flexbox on everything but you really shouldn't. Flexbox is a new layout algorithm for laying out complex web pages/applications, but he also have it disadventages(temporarily the most slower layout). Basically flexbox is the most best for smaller page components and UI elements.
As you only want the text itself to wrap you need to use flex-wrap: nowrap; to keep . right on the same line. The text will automatically wrap when there is not enough space.
The initial value of the flex-wrap property is nowrap . This means that if you have a set of flex items that are too wide for their container, they will overflow it.
Disadvantages. While flexbox is supported by most major browsers, it's still newer than the traditional box model. This means older browsers don't support it as well (some not at all). There are also more inconsistencies across different browsers.
I don't think that exactly what you want is possible without JS based iterative layout logic (you know, let the browser render, calculate widths and conditionally add/ remove classes).
I think however that the solution given in this fiddle is a sane CSS only approach. There are basically two layouts, the wide one where I only made one change flex-wrap: nowrap;
to prevent the nasty case you describe where not all three elements are wrapped. And the narrow one which overrides the the flex-direction to flex-direction: column;
. Both can easily be switched with applying a proper media-query with a sane min-width
.
Not exactly what you are asking, but (may be) even better. You can set it without any divider. You will get the illusion of the divider when needed, but no divider when not
#wide {
width: 31em;
}
#narrow {
width: 10em;
top: 100px;
}
.container {
position: absolute;
border: solid red 1px;
background-image: radial-gradient(circle at center, blue 5px, transparent 5px);
}
.fakecontainer {
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
margin-right: -1em;
}
select {
flex-basis: 11em;
flex-grow: 1;
margin-right: 1em;
}
select:nth-child (2) {
flex-basis: 10em;
}
<div class="container" id="wide">
<div class="fakecontainer">
<select multiple>
<option>One of many</option>
<option>Two of many</option>
</select>
<select multiple>
<option>One of many</option>
<option>Two of many</option>
</select>
</div>
</div>
<div class="container" id="narrow">
<div class="fakecontainer">
<select multiple>
<option>One of many</option>
<option>Two of many</option>
</select>
<select multiple>
<option>One of many</option>
<option>Two of many</option>
</select>
</div>
</div>
You just need an extra element, fakecontainer , to do some hack with the margins
If you really want a divider in the narrow option, you just need to do a similar trick with the bottom margin (let me know if this is the case)
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