Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I force wrapping of all items with CSS flexbox?

Tags:

css

flexbox

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:

  • To have the middle (divider) element take up the minimum amount of space possible.
  • To have the element on either end (ie: the select controls) have a minimum width, and grow to fill the possible space.
  • To have all three elements on one line when there's enough horizontal space in the container (ex: the browser width)
  • To have all the elements wrap vertically when there's not enough horizontal space to position them all horizontally.

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?

like image 409
Craig Walker Avatar asked Feb 04 '15 04:02

Craig Walker


People also ask

Can I use flexbox for everything?

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.

How do you wrap content in flexbox?

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.

Why is flexbox not wrapping?

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.

What are the disadvantages of using flexbox?

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.


2 Answers

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.

like image 70
vanthome Avatar answered Sep 30 '22 03:09

vanthome


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)

like image 29
vals Avatar answered Sep 30 '22 03:09

vals