2

I'm pretty new to Flexbox, but I'm using it in a web project to move embedded video players around in a <div> element using the order property. It works perfectly for this. This is all displayed on one line. In the diagram below, those video players are in the "on deck" area, in a <div> with flex-direction: row.

My web application is laid out like this (roughly):

CONTAINER - flex direction column.
 ---------------------------------------------------------
|                                                         | "menu bar"
 ---------------------------------------------------------
| iframe. Flex 6                         | iframe. Flex 1 | "main area"
|                                        |                |
|                                        |                |
|                                        |                |
|                                        |                |
|                                        |                |
|                                        |                |
|                                        |                |
|                                        |                |
 ---------------------------------------------------------
| iframe      | iframe       | iframe        | iframe     | "on deck" area
|             |              |               |            |
|             |              |               |            |
 ---------------------------------------------------------

Each of those areas named on the right of the diagram is a <div> with flex-direction: row.

What I'm hoping to accomplish is to combine the "main area" and "on deck area" into a single div flex row, and to always have the two iframes currently in the "main area" show up on one line, with all of the iframes in the "on deck" area below it. So the flex 6 iframe would be order 0, the flex 1 iframe next to it would be order 1, and everything below it would be order 2, 3, etc. That way, those iframes could be moved into and out of that "main" area without having to reload, which has a performance hit I'd like to avoid if I can by changing each iframe's order.

I know there's a property called flex-wrap which can let elements in a single div wrap to the next line if they don't fit. I'm having trouble wrapping my head around this.

My question is - is there some way I can force flex iframes to always appear on the first line of a div where flex-wrap is set to wrap?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Argus9
  • 1,863
  • 4
  • 26
  • 40

1 Answers1

4

I think you have the right idea with flex-wrap. You can combine all items in main area and on deck in one flex container, and have them wrap to form your desired layout.

To make this work, you'll also need the flex-basis property to set the widths for Flex 6 and Flex 1.

For instance, you'll tell Flex 6 to be 70% wide, and Flex 1 to be 30% wide. This makes both items occupy 100% of the line, forcing all other items to wrap to the next line.

Here's a DEMO.

.container {
    display: flex;
    flex-wrap: wrap;
    border: 1px dashed black;
    width: 720px;
}

.box1 { order: 0; flex-basis: calc(70% - 20px); }
.box2 { order: 1; flex-basis: calc(30% - 20px); }
.box3 { order: 2; flex: 1; }
.box4 { order: 3; flex: 1; }
.box5 { order: 4; flex: 1; }
.box6 { order: 5; flex: 1; }

.box {
    height: 50px;
    width: 100px;
    margin: 10px;
    background-color: lightgreen;
    box-sizing: border-box;
    
    /* non-essential; for styling numbers only */
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3em;
}
<div class="container">
    <div class="box box1"><span>1</span></div>
    <div class="box box2"><span>2</span></div>
    <div class="box box3"><span>3</span></div>
    <div class="box box4"><span>4</span></div>
    <div class="box box5"><span>5</span></div>
    <div class="box box6"><span>6</span></div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    Michael, thank you so much! This is exactly what I was trying to accomplish. I'll give that a try tonight and report back. – Argus9 Jan 20 '16 at 22:23
  • Argh, Michael, I forgot one key point. The "on deck" area is, itself, a div, and it's horizontally-scrolling. The idea is that if there are more than four iframes in the "on deck" area, the user can scroll horizontally to see the other iframes. This is the wall I hit when trying to do this on my own. Is that sort of functionality possible with these goals? I had some really wonky ideas to make this possible, like sticking the two "main" iframes to the top-left and top-right side of the screen, with basically the entire main div horizontally-scrollable. – Argus9 Jan 21 '16 at 01:32
  • Using this solution to your question, there would be no horizontal scrolling because the items would wrap to the next line. [See DEMO](https://jsfiddle.net/mwah48tb/1/). – Michael Benjamin Jan 21 '16 at 01:43
  • You could make the "on deck" area a nested flex container, which could then be a scrollable on overflow. But then the `order` property won't work, because the items in "main area" and "on deck" would be in different containers. [See DEMO](https://jsfiddle.net/mwah48tb/2/) – Michael Benjamin Jan 21 '16 at 01:46
  • Exactly the problem I'm running into. – Argus9 Jan 21 '16 at 01:52
  • If "main area" and "on deck" can stack and scroll vertically, this can work with flexbox. If you want "on deck" to scroll horizontally, not sure flex is the right solution. We could add a horizontal scrollbar to the current solution, but then what happens with the use scrolls right? They'll see a large area of white space where "main div" used to be. – Michael Benjamin Jan 21 '16 at 01:55
  • Yeah, I think that's what it'll come to, Michael. I *really* want the main iframes in view at all times - do you think that's possible with flexbox if it scrolls vertically? I feel like maybe sticking them to the top-left and top-right might do it. – Argus9 Jan 21 '16 at 01:58
  • It's a common request with no easy workaround. See [**here**](http://stackoverflow.com/q/6794000/3597276) and [**here**](http://stackoverflow.com/q/5209814/3597276). It will be easier once [**position: sticky**](https://developer.mozilla.org/en-US/docs/Web/CSS/position#Sticky_positioning) has [browser support](http://caniuse.com/#search=sticky). – Michael Benjamin Jan 21 '16 at 02:21
  • 1
    Alright Michael, I'm going to give this some thought and see what I come up with. Thank you for all the suggestions! – Argus9 Jan 21 '16 at 02:29
  • Is there some reason that won't work in other browsers using `position: fixed` or `position:absolute`? – Argus9 Jan 21 '16 at 17:50
  • `position: sticky` currently only works on Firefox and Safari. `position: absolute` positions an element in a containing block; it doesn't fix anything in place relative to the viewport. `position: fixed` will fix the element relative to the viewport, not the parent container. You could play with `fixed` however. Depending on your overall use-case, it may work for you. – Michael Benjamin Jan 21 '16 at 20:51