产品设计

Learn You a Flexbox for Great Good!

微信扫一扫,分享到朋友圈

Learn You a Flexbox for Great Good!
0

Yet Another Note (2012-05-13):
It might be obvious that the flexbox spec is changing often, but a kind commenter suggested I add a note here regarding the fact that in the spec, the flex() function has been replaced by the `flex` property
, which makes plenty of stuff in this article obsolete. Also, expect more
to change. I will most likely leave this article as is. I will write an update as soon as I see an implementation in at least one more browser. As of this note’s date, Chrome still supports the version described below. —Stephen


Note (2012-05-12):
I have added -moz-, -ms- and -o- vendor prefixes to all code examples and the demo. Here’s why
. The spec is—at the time of this note—still in flux, so I intentionally left out the non-prefixed properties/values.

So you want to learn Flexbox? Perhaps you’ve heard about it. Perhaps you’ve read atutorialor two about it. Perhaps you’ve even played around with it already.

If you’ve never heard of Flexbox, or if it’s been awhile since you’ve used it, forget what you know. We’re starting over! The spec has been rewritten; the last version at the time of this writing is dated 29 November 2011!

What you’ll need

Currently
At the time of this writing
, Chrome Canary
Google Chrome
has a partial implementation of the spec. If you’d like to follow along, you’ll need nothing more than Chrome Canary
Google Chrome
and your favorite text editor.

Ready? Let’s get to it!

What is Flexbox?

Flexbox is a nickname for CSS Flexible Box Layout Module. It’s one of a few CSS Working Drafts having to do with visual layout. Flexbox offers us a new box model which has been optimized for laying out user interfaces. In short: the children of a “box” can be ordered either vertically or horizontally within their parent, and we can control what happens to any remaining space. It is possible to nest these boxes, allowing for very complex layouts.

Caution!

There are other CSS layout modules in development which, in my opinion, are much more suited to general page layout than Flexbox. Flexbox is fairly straightforward, but can become unruly when used for complex layouts. In any case it is not the best solution for all types of layout
. But for UI-components like buttons, forms, toolbars or rows and columns of content/media blocks for which you’d normally use floats, Flexbox makes code simpler and is a huge time-saver. Flexbox is designed to play nicely with existing CSS properties. Thus, you are still free to use floats or other types of positioning on non-Flexbox elements.

Three Little Boxes

If you’re feeling a bit lazy, you’re welcome to simply download and edit thedemo pageOtherwise…

Open your editor, create a simple HTML document with a single box. In this case, we’ll use a div
:


    
    
        
             
             Flexbox
        
        
            

Great, But it would be nice to see something, so we’ll have to add some style:


    
        body>div {
            height: 500px;
            padding: 1em;
            background-color: gray;
        }
    

Now we’ll put three boxes into our div
. These are, of course, the first div
‘s children:


    
A
B
C

Let’s style those as well:


    div>div {
        width: 100px;
        height: 100px;
        background-color: pink;
    }

Now look at this page in

Canary
the browser
. Nothing unusual here, just three block-level elements one under another, as block-level elements are known to do. But we’ll put a stop to that
. We’ve created our own Flexbox playground, so let’s play.

Defining a flexbox

We would like to apply the magic of Flexbox to the children of our parent div
. We do so with the display
property. By applying display: flexbox;
to our parent div
, we tell it to use the Flexbox box model. If we wanted our parent div
to be inline instead of block-level, we’d use display: inline-flexbox;
.


    body>div {
        display: -webkit-flexbox; /* We need the prefixes for now, unfortunately. */
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Our three child div
s, which we’ll call flexbox items
from now on, now live according to the Flexbox box model. Beware: there are rules that determine what a flexbox item is. For example, if we were to use position: absolute;
on one of the three boxes, it would no longer be a flexbox item
since we’ve applied a different positioning model. Read more about flexbox items
in the spec.

Back to our little exercise. Take a look at the page in your browser. The flexbox items look a bit as if we had applied inline
, inline-block
or float
to them. This is because the Flexbox default is to position flexbox items horizontally. The main difference so far is that we have only added a rule to the parent
and not to the items themselves.

Source-order independence

Flexible Box Layout Module gets its name from the fact that it allows us to create flexible boxes. In other words, boxes can become flexible by utilizing available space. We’ll get to that in a minute. But Flexbox offers something at least equally important to us, especially in this Age of Mobile: source-order independence. Let’s play around and see how we can change the order of flexbox items.


    body>div {
        display: -webkit-flexbox;
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox; 
        -webkit-flex-flow: row-reverse;
        -moz-flex-flow: row-reverse;
        -ms-flex-flow: row-reverse;
        -o-flex-flow: row-reverse;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

OMG. Our flexbox items are now right-aligned and the order is reversed! We do this with the flex-flow
property, for which row
is the default value. row-reverse
flips this around. You might have already guessed that when you want to position flexbox items vertically, you would use column
or column-reverse
. At the time of this writing,

Canary
Chrome
does not support column-reverse
, but try out column
and see what happens! When you’re done playing around, set the value back to row
and we’re ready for our next step.

By the way, flex-flow
also takes a value for wrapping flexbox items to new rows (or columns, depending on which you’re using). The values wrap
and wrap-reverse
serve this purpose, as the default is a single row (or column) of flexbox items which overflows the parent. wrap
and wrap-reverse
still haven’t been implemented at the time of this writing (I’m saying that a lot). But let’s say, just for fun, that we could use wrap
today:


    body>div {
        display: -webkit-flexbox; 
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        -webkit-flex-flow: row wrap; /* `wrap` gives us a multi-line flexbox. */
        -moz-flex-flow: row wrap;
        -ms-flex-flow: row wrap;
        -o-flex-flow: row wrap;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Mirror, mirror…

All the properties dealing with order, direction or alignment of flexbox items are influenced by the current writing mode
. The writing mode is the original direction of the text. Many of us are used to top-to-bottom, left-to-right. But as soon as these are changed, the output of the directional Flexbox properties will also change. You’ve already seen what row-reverse
does. But what if your writing mode isn’t the default (top-to-bottom, left-to-right) but top-to-bottom, right-to-left? Your flexbox items would be laid out from right-to-left in the first place
, and row-reverse
would flip things so they’re left-to-right.


    body>div {
        display: -webkit-flexbox; 
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        direction: rtl; /* The `writing-mode` property currently has no visual effect in Chrome. The `direction` property will suffice for our example. */
        -webkit-flex-flow: row;
        -moz-flex-flow: row;
        -ms-flex-flow: row;
        -o-flex-flow: row;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Look at the page in your browser. Now replace row
with row-reverse
. See what happens?

Confusing? Perhaps a little at first, but the properties all work logically based on the current writing mode. As most of us usually work with the same writing mode most of the time, it shouldn’t be much of a problem.

In order to understand the effect many Flexbox properties have on flexbox items, it is important to understand what the main axis
and the cross axis
are. The main axis
is the axis along which the flexbox items are placed. In other words, if the flexbox items have been placed horizontally ( flex-flow: row;
), then the main axis is horizontal. The cross axis
is perpendicular to the main axis. In our example, that would be vertical. When using flex-flow: column;
, this is switched: the main axis is vertical and the cross axis is horizontal.

That’s a pain to explain well. Just to be sure we’re clear, here’s an illustration:

Remember main axis and cross axis, because we’ll need them in a bit.

Order! Order in the court!

Let’s look at another property which helps the cause for source-order independence: flex-order
.

In your example code, make sure you’ve set flex-flow
to row
and have removed direction: rtl;
. If things are as they should be, you’ll have three flexbox items: A, B and C, in the top left of body>div
. Imagine that although our code contains these items in that order, that we want to display them in the order A-C-B. To do this, we’ll use flex-order
:


    div:nth-child(2) { /* Yes, I could have used an ID or a class. But, hey, whatever. */
        -webkit-flex-order: 1;
        -moz-flex-order: 1;
        -ms-flex-order: 1;
        -o-flex-order: 1;
    }

Check things out in your browser. The order of the flexbox items should be A-C-B.

flex-order
places flexbox items into ordered groups
. Boxes without an explicit flex-order
are in group 0 and remain in source order. In our example, the second flexbox item (B) is placed in group 1. A and C remain in group 0 and in source order (A before C). Since group 1 comes after group 0, the B comes last. If we had wanted the order B-A-C, we could have left B in group 0 and put A and C into group 1:


    div>div:first-child,
    div>div:last-child {
        -webkit-flex-order: 1;
        -moz-flex-order: 1;
        -ms-flex-order: 1;
        -o-flex-order: 1;
    }

Flexibility

One of the nicest aspects of Flexbox is the ability to create flexible elements. We can decide what to do with any remaining space in our body>div
(in this example). We can divide this space up between the flexbox items, or we can make the widths or heights of one or more of these items flexible
, alotting a certain amount of available space to each.

We’ll look at flexibility first and then come back to distributing available space.

Imagine that our three flexbox items are buttons in a web application which might also be used on mobile devices. Sometimes we have three, but sometimes we only have two (just nod and go along with it). We’d like to say, “No matter how many of these buttons there are, I want them all to generally be the same width, and these widths should be such that the row of buttons takes up all the available width of the parent.” We’d normally resort to JavaScript for these types of layout problems, but Flexbox might put an end to that. See what happens when we make our flexbox items flexible with the flex()
function:


    div>div {
        /* width: 100px; */
        width: -webkit-flex(1 0 100px);
        width: -moz-flex(1 0 100px);
        width: -ms-flex(1 0 100px);
        width: -o-flex(1 0 100px);
        height: 100px;
        background-color: pink;
    }

The flex()
function can be used as a value for width
or height
. flex()
takes three values: positive flex, negative flex and preferred size
. The last two parameters are optional; the default for negative flex is 0 and the default for preferred size is 0px. Here’s how flex()
works in a nutshell:

  1. The preferred width
    is applied to the flexbox items.
  2. If there is any space left over in the parent, this space is divided up into parts and added to the widths of the flexbox items according to the positive flex value.
  3. If the flexbox items overflow the parent (e.g. together they are wider than the parent), then the negative flex value is used for determining the widths of the items. Please note that negative flex is a positive
    value (e.g. 2 and not -2).

A positive flex value of 1 basically means “one equal part of the available space”. A value of two would mean something like “twice the amount of available space as the items that have flex(1)
”. So it’s nothing like “two parts whiskey, one part cola”. The easiest way to learn it is to try it out. Type the following code under
your rules for div>div
:


    div>div:first-child,
    div>div:last-child {
        width: -webkit-flex(2);
        width: -moz-flex(2);
        width: -ms-flex(2);
        width: -o-flex(2);
        background-color: magenta; /* This allows us to see the difference clearly. Plus, it hurts your eyes. */
    }

If you check your browser, you’ll see that the first and the last flexbox items don’t each have 2 parts of the available space. Rather, they have two times as much
available space as the middle box, which has flex(1)
. I know, I know. Just be glad you’re not a browser maker. Unless you are, in which case: have fun and please get this implemented ASAP!

Also, please note that this does not
mean that the two outermost boxes are two times as wide
as the center box. We’re only dealing with how the available space in the parent is being distributed.

Remove the declaration you just added. Remove one of the div
s and look at the result in your browser. Once you’ve seen what happens, put the div
back in again.

There’s plenty more about flex()
and any other gory details you might want to know about Flexbox; these can all be found in the spec
.

Alignment of flexbox items

Did you remember everything about main axis and cross axis? Excellent. Because the flex-pack
property determines how flexbox items are aligned along the main axis. In our example file, the main axis is horizontal. In order to study the effect of flex-pack
, remove flex()
and change the width back to 100px:


    div>div {
        width: 100px;
        height: 100px;
        background-color: pink;
    }

flex-pack
accepts one of four possible values: start
, end
, justify
and center
. Pretty clear. Let’s center our flexbox items. We do this on the parent:


    body>div {
        display: -webkit-flexbox;
        display: -moz-flexbox;
        display: -ms-flexbox;
        display: -o-flexbox;
        -webkit-flex-flow: row;
        -moz-flex-flow: row;
        -ms-flex-flow: row;
        -o-flex-flow: row;
        -webkit-flex-pack: center; /* <-- */
        -moz-flex-pack: center;
        -ms-flex-pack: center;
        -o-flex-pack: center;
        height: 500px;
        padding: 1em;
        background-color: gray;
    }

Go ahead and play with the other values until you like it.

Of course, there is a property for aligning flexbox items along the cross axis
: flex-align
. The possible values differ slightly from flex-pack
. The most important thing to remember is that while flex-pack
is applied to the parent
of the flexbox items, flex-align
is applied to the flexbox items themselves
.


    div>div {
        width: 100px;
        height: 100px;
        background-color: pink;
        -webkit-flex-align: center; /* Also: start | end | baseline | stretch  <-- Try these vales as well! */
        -moz-flex-align: center;
        -ms-flex-align: center;
        -o-flex-align: center;
    }

Not all the values are supported yet, but I don’t think we’ll need to wait very long. As the spec solidifies, implementation should come fairly quickly. The browser makers are quite interested in Flexbox.

Enough! Time to play

There are a couple of other properties having to do with multi-line flexboxes, but since we can’t try those out yet, we’ll stop here for now. Hopefully we’ve handled enough material to get you started playing around with the “new” Flexbox. Try and consider practical applications. How could Flexbox help within the context of “responsive design” and mobile? What possibilities open up for form styling? Navigation?

You don’t need to be able to use this today in actual projects to learn and experiment with the possibilities. Implementation might come quicker than you think, and you’ll already have a head start.


Note: This article first appeared in the Dutch language
for the Fronteers Advent Calendar
. Payment for the article was a modest donation to ICCF Holland
.

阅读原文...


微信扫一扫,分享到朋友圈

Learn You a Flexbox for Great Good!
0

Avatar

Opting Out of New Year’s Resolutions

上一篇

Ideal soliton distribution

下一篇

评论已经被关闭。

插入图片

热门分类

Learn You a Flexbox for Great Good!

长按储存图像,分享给朋友