Putting Flexbox into practice by Zoe Mickley Gillenwater
I'm going to be talking about putting Flexbox into practice.
And as Paul said-- is this clicker working? No.
I'm a web designer and front end developer.
I wrote these two books, as he mentioned.
And I'm pretty proud of them.
I think they stand up well over time.
But I don't quite feel the same way about this website that I created about 13 or so years ago.
This was my first portfolio website promoting my awesome web design skills.
And so notice how the circle's cut off on the bottom? That's because I designed it to fit exactly 800 by 600 windows.
It looks awful on any other size.
Apart from that, I don't think the design is that bad.
It's kind of like flat design before its time, isn't it? But it was laid out with a table, as all sites were at the time.
And this is a pretty gnarly table, isn't it? But we had no other way to create multi-column layouts.
Some of you have probably never created a layout with a table, but let me just say they had a lot of weaknesses.
And in 2003 I started a new job, and my boss had heard of this idea that you could create layouts without tables-- just with CSS.
And he wanted to try it.
Now I had heard of CSS for text formatting, but that was about it.
So, I was blown away by this idea as well of pure CSS layouts and I read up on it.
I learned that table free layouts were primarily created with CSS floats.
And by 2004 I had switched to float based layout completely-- got good at it.
But floats weren't designed for creating full page layouts, so I definitely ran into, you know, challenges and limitations that made float layout frustrating sometimes.
For instance, having to deal with floats hanging out of their containers, or wrapping when there's not enough space.
Also your visual location is somewhat dependent on your HTML order, since floats don't move up.
They only move over to one side.
And of course there are the classic complaints that you can't make separate floats match each other in height.
You can't center a float.
Of course most of these things can be worked around in various ways.
But they are complications that have to be worried about and fiddled with every time, instead of features that just work.
So, the CSS flexible box layout module, which is called Flexbox for short, solves a lot of these shortcomings.
It's one of many layout mechanisms that has been added to CSS in the last couple of years.
And it makes building fluid, responsive, and adaptive layouts much easier than our current layout methods.
You can also use it for fixed width layouts, too.
But it has been a Candidate Recommendation since September of 2012.
So it is quite solid and well vetted now.
Before it was a Candidate Recommendation, though, it did go through a lot of changes-- the syntax did-- and different browsers support different versions of the syntax.
It can be hard to keep track of which is which, but the display value is a great indicator.
So, if you're looking at tutorials or demos-- tools online, you can check that out to get a sense of what version of the syntax they're using, and thus which browsers it will work in.
But to turn on Flexbox you set display flex on a wrapper to make it into a flex container.
And indicate that you're using a new box model on its children, which are now called flex items.
And only the direct children are flex items, not all descendants.
And this can be limiting, but you can nest flex containers by turning a flex item into a flex container itself, as well.
Once I've created my flex container, I need to specify the flow direction of the flex items within it.
They can be laid out side-by-side or stacked vertically.
The default is side-by-side, running from left to right.
But I can change this using the flex-direction property set on that flex container.
And as you can imagine this makes Flexbox great for responsive web design, since I can change the orientation easily at different screen sizes.
To demonstrate these Flexbox properties, I created a site devoted to s'mores, because they are delicious.
How many of you have had s'mores? See? Yeah, only a few people.
So it is a dessert in the U.S. that you make typically
when you go camping by roasting a marshmallow over the fire, and then you sandwich it with chocolate in between graham crackers.
And I'm kind of obsessed with coming up with crazy s'mores combinations on that various theme.
But apart from that, this is a demo Flexbox, obviously, so you should use a browser with good Flexbox support to check it out.
Chrome and Opera seem to be the best here.
But there are a few fall backs in there for non-supporting browsers, as we'll talk about later.
And I'm going to go over the Flexbox CSS for various parts of this s'mores builder page throughout the rest of this presentation.
But a simple way to see how (display)flex and flex-direction work is with the main nav.
I built the site mobile first, so at narrow screen sizes I wanted the links to lay out in a row, all underneath the logo.
(so i just set display)flex on list-nav, which is the UL.
And this in turn sets the flex-direction to the default value of row, so the children Li become flex items laid out on a single horizontal line.
So, here's how the main nav then looks on narrow screens.
The links went from stacked to horizontal.
That is really washed out here.
But you're probably not impressed with those screenshots, because you can easily put links on the same line with each other (using display)inline, lots of other CSS.
That's totally true.
We're simply laying the groundwork here for the cool stuff that's coming.
I'm showing you how to set up the flex container, but we haven't really started manipulating the flex items inside it yet.
But now that I've shown you one code sample, I ought to point out that the CSS in the real world might look a lot more complicated than what I showed you because of these browser variants.
So this shows two properties using all of the syntaxes and prefixed versions for browsers that are currently in use.
Chrome and Firefox are the only ones that support non-prefixed, current syntax.
And I'm not saying that you ought to include all of these variants, but this is what the simple code sample that I showed you earlier would look like if you did.
And it's definitely tough to keep track of which properties and values correspond.
One tool that I like to use is called flexy boxes.
It's a Flexbox code generator that includes Legacy Flexbox CSS if you want it to.
And so you can plug-in your values there and see what the alternate versions would be-- to see the equivalents.
If you use Sass or LESS you can use the Flexbox mix in to create all of those variants for you, or at least the variants that you want.
Again, because I'm not saying you have to do all of them.
Another option is the prefix-free script.
Keep in mind, though, that it only adds prefixes to whatever syntax you write.
So you have to write in the different syntax manually-- whichever ones you're choosing to use without the prefixes if you want the script to then add the prefix versions of that different syntax.
So if you're already using that prefix-free script, that's going to help you out with Flexbox as well.
Now I'm kind of undecided on whether you should use all of the old syntaxes.
Like most things in web design, I think it depends on the project, and which pieces of Flexbox that you're utilizing.
The bottom line is this.
You go ahead and use whichever variants you want, or none of them.
But to keep the CSS that I use-- that I'm going to show you from being super long and hard to read, I'm going to emit all the prefixed versions from the code samples on these slides.
Again, and that doesn't mean that I'm saying that you shouldn't use any prefixed versions in the real world.
I'm just trying to keep things simple and clear here.
And I have included most of them in the live demo, so you can go there and check out the CSS to see the alternate syntaxes there.
So, anyway, now that's all out of the way, let's get back to talking about flex-direction.
Even though I don't have to manually set flex-direction to rows since it's the default value, it's important to keep in mind what the flex-direction is.
Because it determines which direction will be what Flexbox calls the main axis, and which will be the cross axis.
When flex-direction is set to row, my flex items flow horizontally-- so that's my main axis, and width is my main dimension.
That means the vertical axis is my cross axis, and height is my cross dimension.
And this is all reversed if flex-direction is set to column.
And these axes are important because they affect all the Flexbox properties that will come later.
Flexbox is so flexible, because it allows you to layout and align items in any direction, but it basically needs to know at which point to start and move out from.
It also needs to know whether to lay out the flex items on a single line, which is the default, or onto multiple lines.
And this is controlled by flex-wrap.
It also controls which direction the new lines stack in.
So for row, do I want the rows stacked top to bottom, or bottom to top? For column, do I want the column stacked left to right, or right to left? This property controls that.
Flex-wrap is extremely useful, but a major problem with it is that Firefox doesn't support it.
It doesn't support the old box lines property either, so you can't feed it anything to work around this lack of support.
In fact, no browser ever supported the 2009 box lines property.
So if you are including that 2009 syntax for the benefit of Android and older versions of Safari, you will be out of luck if you want your flex items to wrap.
Another issue is that you have some control, but not complete, ironclad control over where items wrap without support for the break-before and break-after properties.
They are not part of the Flexbox spec, but they would be very useful in conjunction with Flexbox.
But they are only supported by IE10 and Opera for now.
So, I'm still going to show you how to use flex-wrap in these examples because it is so essential, but lack of Firefox support means you probably can't use it just yet.
But flex-wrap is basically the third piece of what we need to set the stage when firing up Flexbox.
You create that flex container (by setting display)flex.
Then set its flex-direction to control the orientation of the items within it to horizontal or vertical.
And set flex-wrap to control whether those items wrap, and in which direction they wrap.
Flex=flow is a shorthand property that can set flex-direction and flex-wrap at one time.
So, let's start digging into how I use these properties on the s'mores site.
There's not much need for Flexbox at the default mobile first styles, which are shown here.
Block layout just takes care of stacking everything into a single column.
But at wider viewports, the s'mores builder page had two main sections that need layout.
There's the builder form here on your left.
And that contains four component boxes, and then an action box at the bottom.
And then there's a gallery of s'mores combinations containing a bunch of gallery item boxes.
As the viewport gets wider, I want to start taking advantage of this space and make some of these items sit side-by-side, so I'll add Flexbox to handle this.
And I don't have to put this in a media query.
I put it in the default styles outside of the media queries, and it just kicks in whenever space allows.
It's kind of like the browser is figuring out content driven breakpoints for you.
So, here's the CSS that creates the flex container for the gallery section.
And for the children flex items-- those dark brown boxes-- I don't need to set explicit widths.
But instead can use the flex property to specify their proportional size, and let the items resize to fit whatever space is available.
This property is one of the foundations of Flexbox.
It's a big part of what makes it so powerful.
But it can be difficult to fully understand at first, so let me break it down.
The flex property is set on Flex items.
And it affects either their width or their height, whichever is the main dimension along the main axis.
Here the gallery items are horizontal, so Flex will affect their widths.
And there are three components to the flex value, which is a shorthand property-- flex-grow, flex-shrink, and flex-basis.
Flex-grow means how much the flex item will grow relative to other items if there's extra space available.
Or you can also think of it as the proportion, or number of shares, of extra space that it gets.
Flex-shrink means how much the item will shrink relative to others if there's not enough space.
Or the proportion of the overflowing pixels that it would need to head lopped off of it to get everything to fit again.
And flex-basis is the initial starting dimension before free space is added on or taken away from the item.
And that can be set to any standard width or height value, including the auto keyword.
So, for the gallery item flex value, I set flex-grow to 1 because I want each item to get one share of the extra width.
I set flex-shrink to 0.
That means don't let the item shrink at all if they can't all fit.
But flex-wrap won't let the items shrink anyway, because once there's not enough room to fit a certain number on the line, it will just wrap them instead of shrinking them.
So, in this case that means that flex-basis basically becomes min-width.
So, each item will start out at 200 pixels wide.
The browser will put as many of those 200 pixel boxes as it can on a line, then it will wrap.
And then it will expand each of those boxes if needed to fill up the extra width on the line.
So they'll always be at least 200 pixels wide.
Flex is one of those things that you just have to see live, so let me try to switch to Chrome now to take a look.
I think I need to drag this over.
Oh, well, it maximized.
So here it is at a narrow view.
And as I expand, they will jump up.
And when they have enough space to fit two to a line, they would jump up and do so.
And again, as I get wider they will continue to wrap to the number that will fit on each line.
And again, this is not controlled by a media query.
I'm not having to say, OK.
At this width now make them each 33% wide so that I can fit three on a line.
The browser just figures this out.
It's similar to having a gallery where you have items set to inline block where they can wrap onto multiple lines.
But here they will fill the entire width of the line at all times.
As opposed to when you use inline block, you'll be left with a gap at the ends of the lines until there's finally enough space for the next item to jump up into that gap.
So that's kind of the main difference here.
Now, when you're reading about Flexbox you often see single-digit flex values in the examples.
And it is fine to use a single digit, but you need to know that digit becomes the flex-grow value.
So when flex-shrink is left off, it gets set to 1.
And when flex-basis is left off, it gets set to 0 pixels.
So be careful with this, because you may not want flex-basis to be 0.
Remember that when wrap is on, flex-basis basically becomes min-width.
So you're saying that you're fine with your items shrinking all the way down to 0 pixels.
And if every thing can get down to 0 pixels and doesn't have other stuff like margins to give it dimension, then nothing ever has any reason to wrap.
I learned this the hard way when I was trying to lay out the builder section of the page, shown here.
The four tan boxes each have the component class on them.
The bar below with the field to name your s'mores in the button has the action class.
And my thought process went like this.
I want all four components to be the same width, so I'll set flex to 1 for each of them.
And then to force the action section to a new line, I will give it flex-basis of 100%.
Because if it's 100% wide, it won't fit on a line with anything else, so it will have to wrap onto a second line.
And this is what I ended up with.
Everything was completely squished and overlapping over here on the left side of the page.
I was totally baffled.
Angry comments were written into the CSS during this period.
What was happening was that by setting flex to 1, I was inadvertently setting flex-basis to 0, which allowed all four component boxes to shrink down to 0 pixels wide.
This was an early skeleton of the page before I had added any borders, or padding, or margins to those component boxes.
So if they take up literally no space, then it's perfectly fine for a 100% wide box-- the action box-- to sit on the same line with them.
And that's exactly what happened.
It shrunk them to 0 pixels only because it had a 100% wide box that it was trying to fit to.
And my flex value of 1 told the browser that it was OK to do this.
But changing flex-basis to 200 pixels meant that the components would start out at that width.
So when the browser would go to add on that 100% wide box, it would never have room for it on a line with any of those component boxes.
And it would always wrap it to a new line by itself.
Let me show you that builder section in Chrome now.
This is hard to see because of the light color.
But basically it starts out, you know, all the boxes stacked.
Then as I get wider it goes 2 by 2.
Wider again it goes 3 by 1.
And I'm OK with this, because s'mores have these three standard, traditional components, so those are fine altogether.
And then this is like the crazy accessories extra things, so I'm fine having that being separated out.
So I kind of like this layout.
And then if I get wider still-- I'm not sure if I have enough space to make it happen.
But it will go four all in the same line together with this action box down below.
And again, none of this is in a media query.
This is all controlled with those same few lines of CSS that I already showed you outside of that media query.
It's controlling all of these different layouts.
So, being able to use Flex has several advantages over having to set explicit widths or heights.
You've already seen how dramatically a layout can change without having to create different versions within multiple media queries.
Here again, there's four different layouts that the builder section goes through.
And they're all controlled by those same few lines of CSS outside of that first media query.
So I don't have to figure out where to put the breakpoints, and what crazy percentage widths to give those boxes within each breakpoint.
The browser figures out all of that.
You will still need media queries.
I still love media queries.
But it's nice any time that you can automate things and keep your CSS simpler.
Flex also adjusts widths to accommodate margins.
Box sizing is commonly used nowadays to take care of border and padding, but it doesn't do anything with margin.
So if-- of course if I was trying to make all four component boxes each 25% wide with 20 pixels of margin, they wouldn't all fit.
The margin is added on.
But with Flex the margin is accounted for in calculating how much space is available so all four component boxes can fit perfectly.
The browser would also make them fit if I added or removed items into the HTML without me having to adjust any CSS.
Which makes Flexbox really useful on sites where the number of blocks of content may change frequently, or based on user interaction, or just based on the section of the site that you're in.
So maybe on your home page you have three blocks sitting side-by-side for three features of your widget that you want to highlight.
And then on the features page, you want to show five feature blocks.
And then a month from now your boss decides that she wants to add a sixth block.
You don't have to change the widths in CSS or use different classes on the same items when they're in different sections of the site.
The flex property of Flexbox can take care of this for you.
It makes your HTML and CSS a lot more modular since you can move items around anywhere within the site and have them adjust in size automatically.
Flex is great to use in hybrid layouts, as well, when you're using different units of measurement across a line.
So, like here, I wanted the text field to stretch to the remaining width of its line.
There's a text field next to that label Other.
But I have no idea what width value to give it, because the content before it has widths in a mix of pixels and Ems, and then the parent box is some changing percentage of the page.
Using Flexbox I simply use the flex property to tell the text input, which has the other name class, to take up all the remaining space.
Now the Radio button and the Label are flex items to since I set their parent ally to be a flex container.
But I don't set them to flex, so they just size to their content or pixel dimensions.
Only the text input flexes.
So if the parent component box is narrowed or wide, the text input always stretches to fill the rest of the line.
Another really cool thing about flex is that it can make siblings have proportional sizes to each other.
If I set two boxes to Flex 1, and one box to Flex 2, the Flex 2 box will be twice as wide as the other.
So the browser first allocates pixels to padding and margins, then it sees how many are left for flex widths.
And it gives two pixels to the Flex 2 box for every one pixel that it gives to each of the Flex 1 boxes.
So you can think of it like grid units in a CSS framework.
This red box is 2 grid units wide-- as if I had set a class of span 2 or something on it-- while the others are only 1 grid unit each.
It's just that these grid units are totally flexible and determined by the browser instead of me having to calculate them.
But you have to be careful with this, because, again, it only works as you expect a flex-basis is 0 as it is when you're using single-digit flex values.
This is because if all the boxes start out at 0 pixels, then all the pixels on the line are extra.
So the Flex 2 item will get twice as many of these pixels added on to its 0 width, and is thus twice as wide as the others.
But if flex-basis isn't 0, the Flex 2 item won't necessarily be twice as wide as the Flex 1 items.
The browser will still give it 2 pixels for every 1 pixel that it gives to the others, but it will be adding this pixels on to starting widths.
So for instance, let's say the total width available on this line is 50 pixels.
And if flex-basis is 10 for all three boxes, that means they take up 30 pixels just starting out, leaving 20 pixels of extra to divide between them (in a ratio of 2)1.
That means that each Flex 1 box gets 5 pixels extra, and the Flex 2 box gets 10 pixels extra-- twice as much.
That means that the Flex 1 box will be 15 pixels wide.
10 pixels of flex-basis plus 5 pixels of extra.
And the Flex 2 box will be 20 pixels wide.
10 pixels of flex-basis plus 10 pixels of extra.
And 20 pixels is not twice as wide as 15 pixels.
Right? So, this isn't a knock on Flex.
But it's just a detail about it that most online tutorials leave out, which can trip you up if you don't understand why it's happening.
And again, it did trip me up as well.
I learned this the hard way as well.
But Flex is still awesome.
This is just something that you need to know about it when you're working with those flex values.
So, that gives you a taste of how Flexbox can be used to create an entire page layout.
But with browser support where it's at, you probably don't want to use Flexbox for the entire layout on a live site just yet.
However, you could use it now in smaller ways as progressive enhancement.
Let me show you a few examples where Flexbox could be used on components of the page, rather than the full page layout, in a way where non-supporting browsers still get an acceptable fallback experience.
Sometimes you'll have a simple form with only one or two fields that you want to stretch across a single line the full width with all the items either vertically centered with each other or equal height.
This is common for a site search form, or a login form, as shown here.
You may also see it on an email subscription form, or a product listing in an order form.
On the s'mores site I wanted to use this layout for the Action section.
Without Flexbox I can set each item to be inline or inline block, and use vertical line to get everything centered.
But that doesn't make the text input stretch to fill the line.
With Flexbox I just set the input to flex, and I leave the label on the button at their default content driven widths.
And then the input will take up whatever space is left.
Now a nice bonus to creating a flex container is that all of the items-- here a label, an input, and a button-- stretch to the height of the tallest one.
In this case, the button.
And this is due to the align items property being set to stretch by default on flex containers.
The line items property aligns flex items in the cross axis.
This form uses the default flex-direction of row, so the cross axis is vertical.
So line items affects the item's vertical alignment.
So, as you can see, you can use stretch to make things be equal height.
You can use center to vertically center things.
So, finally equal height columns and vertical centering-- which have been two of the most stupidly impossible facts for CSS to accomplish-- are now as simple as setting a property.
So here's how the Action section then looks with the input flexing to fill the line.
[COUGHS] This accomplishes all of the criteria that I had for this design pattern.
But having the label stretch to the height of the button and input doesn't look very good.
So all I got to do is set align-self to center on the label to override its align item's value of stretch.
And then it will be vertically centered, while the other two items match in height.
And this align-self property has all of the same values as align items.
It just applies to individual flex items, while align items is set on the container and applies to all of the flex items as a group.
So with align items and align-self you have total control over alignment now.
For non-supporting browsers the form can fall back to the appearance where everything's on one line-- but not full width as we saw earlier-- by simply adding back in text align center to the action wrapper.
And this won't have any effect on Flexbox supporting browsers since they're stretching to fill the line.
Non-supporting browsers just ignore the Flexbox properties and values, so the CSS here can coexist peacefully.
I am highlighting the flex properties in red in these examples so that you can see that it's only a tiny bit more CSS to add Flexbox as progressive enhancement.
On narrow screens a different fallback approach might be to stack and horizontally center the items, and then add a few Flexbox properties to enhance the appearance in supporting browsers.
Now I can set the input to display block and width 100% so that on non-supporting browsers it will take a full line.
But the Flex 1 on it will effectively override this, and let the input flex so that it will fit next to the label in Flexbox supporting browsers.
So here's what that looks like in non-supporting and Flexbox browsers.
So that in the non-Flexbox browsers the input is on its own line underneath the label on top of the button, and it's full width.
But in the Flexbox version it sits next to the label.
And I didn't have to hide either of these conflicting chucks of CSS from the other browser, which is really nice any time you're using-- you're trying to do progressive enhancement if you don't have to worry about hiding things.
Now much of the time Flexbox and fallback styles can co-exist like this.
But occasionally they will conflict and you'll only want to apply a certain property if Flexbox is in effect or vice versa.
And the Modernizr script is perfect for this.
It can detect whether the browser doesn't support Flexbox, supports the old version, or supports the current version.
And then it adds the appropriate class to the HTML tag.
In the case of the Action section, the only tiny piece that I needed to hide from non-Flexbox browsers was the right margin on the label.
That only should apply if the label is next to the input.
Because if the label's on its own line, it screws up the horizontal centering of that label.
Now a similar design challenge to the full width form is the full width nav bar.
But here I don't want the items themselves to stretch, I just want them to space themselves out to span the full width.
This is the sort of thing that's really easy to do in Photoshop, but really hard to do on an actual web page.
Right? (using display)table-cell can get you the full width part, but it can't do the equal spacing in between the links.
But if I make the elements flex items, but not flex so they stay at the size of their text, I can then set justify-content to space between.
And that moves the first and last items to the edges, and equally distributes the space that is remaining in between the links.
The justify-content property aligns flex items along the main axis, which in this case is horizontal.
Flex-start is the default value.
But again, space between is what we want here for full width with equal spaces.
[COUGHS] Excuse me.
[COUGHS] I can use both inline block and Flexbox together on the nav so that the items will be centered in non-Flexbox browsers, and full width in Flexbox browsers.
And again, I don't need to hide anything here using Modernizr classes.
[COUGHS] And here's how the nav then looks on medium width screens.
The fallback version doesn't attempt to imitate full width, but there's nothing broken or wrong looking with having the nav be centered.
Now, if your links happen to be all about the same number of characters or mirror each other-- like in this nav where I have two short links on the outside and two longer links about the same length on the inside-- then I may be able to get away (with using display)table-cell as a fallback instead.
And it will make the nav full width, so the fallback will look very similar to the Flexbox version.
Table-cell can't actually do equal spaces, because table cells are sized relative to their content length.
So if the content is longer, the padding within the cell is bigger, so the gaps by longer links are bigger.
But if the links are the same length, you will inadvertently get spaces that are almost equal so it may look fine to the naked eye.
Or it may look so close as to be annoying to the designer eye.
So you'll just have to try it out with your own words in your nav and see how it looks.
But here, again, note (that i have display)table (and display)flex both set on list nav.
I don't have to hide them from each other, (because display)flex just (overrides that display)table in browsers that understand it.
Browsers that don't just ignore (the display)flex and keep using (display)table.
A variation on the full width nav bar is my pagination.
Mine looked too stretched out on really wide screens, so I can keep it centered there.
Again, justify-content center does that for me, but it looks good full width on medium screens, as shown here.
And just like with the nav, I use justify-content space between to do this.
On narrow screens I can keep it full width.
But it would be cool if I could move the previous and next links up to their own row.
But I don't want to change the HTML to do this.
The next link will still be last in that pagination UL.
Flexbox can do this using the order property.
I set that on the flex items to specify which order I want the browser to lay them out on the page regardless of the HTML order.
And the browser runs from the lowest numbers, including negative numbers, up to the highest.
So the previous link comes first with order 0.
The next link comes second with order 1.
And then all the rest of the links come third with order 2.
And this moves the next link right after the previous link, visually.
But we haven't done anything yet to force a new row after the next link.
They're all still on the same row.
I've just moved the next link up right beside the previous link.
To force them onto a new row, I turn on flex-wrap on the flex container.
And then set the previous and next links to 50% wide each so together they take up 100% of the line.
So that means the rest of the links have to wrap down onto a second line.
And I scope this rule to only apply to Flexbox browsers, because it only makes sense to have those links be 50% wide if they are on their own line, which they will only be if Flexbox is on.
Again, someday we can do this with a break-- with the break after properties setting it to always.
But right now using 50% width is a way to force-- [COUGHS] Excuse me.
Force those other links onto a new line.
[COUGHS] This ability to arrange content visually in a different order than it appears in the source can have accessibility implications, both good and bad.
The good thing is that you can keep your HTML in a logical order, instead of making your HTML in some illogical order because it allows you to achieve some particular visual layout.
So that allows screen readers and other user agents that don't pay attention to CSS layout to then present the content in a logical order that you've structured your HTML in.
The downside is that your tab order won't always match the expected visual order of left to right, top to bottom.
At least for left to right languages.
Right? Which can be very disorienting to sighted non-mouse users when their focus outline jumps around the page in a seemingly arbitrary way as they tab around.
The tabbing order depends on the HTML order.
So when you move something visually only using the Flexbox order property, the tab order doesn't change.
For example, in the pagination the user would first tab to the previous link, then the one link, then the two link, until the 10th tab press would take them to the next link.
In this case, I don't think this would be disorienting, because even though the next link is higher the page one link is right below the previous link.
So I don't think it would be strange to see the tab order move there after you were focused on the previous link.
So I don't think there's an accessibility problem with my use of the order property in this pagination example.
But keep in mind that confusing tab order can result if you go crazy with the order property.
I have found, though, that you often can't really use the order property anyway for really extensive reordering.
For one thing since it can only reorder sibling elements, for instance.
Other CSS3 layout modules, like Grid Layout, are going to have much more robust reordering capabilities.
But the order property is still a nice feature to have for smaller layout shifts.
Let's move on to my final Flexbox progressive enhancement example, which is pinning items to the bottom of equal height boxes.
You'll see this often on plan or pricing comparison boxes, as shown here.
Also, may see it in product listings or galleries.
[COUGHS] I wanted to use the effect on the other fields at the bottom of each component box.
Without Flexbox those other fields are unrelated from each other in the HTML, and thus can't align.
With Flexbox, they're still unrelated, but their parent component boxes aren't and they can be equal height easily.
Plus, in Flexbox if you set a margin in the main access to auto it will take up all the free space that is left.
So to pin a flex item to the bottom of its flex container, I can set flex-direction to column on that container so that the items will fill its height.
And then set margin top to auto on the flex item that I want to pin.
And to make a bunch of bottom pinned items appear to be aligning with each other, I just need to make sure that their parents are all the same height.
In our case these parents are the component boxes.
And the default align item's value of stretch on the flex container makes them equal height.
Not only do those component boxes need to be equal height, but the UL within each needs to be equal height with the other ULs as well.
So I make each component a flex container with vertical direction, so that it's child UL will stretch to fill its entire height.
Using height 100% won't work here, because the component box has no explicit width set on it for that height 100% to be relative to.
But setting Flex to 1 will work to stretch it to full height.
So that's another advantage of the flex property here over an explicit dimension.
I also make the UL into a flex container so that its Li elements will be flex items, and can thus use auto margins in this new way.
[COUGHS] Finally, I give the other row the last Li child of the UL and auto top margin, so that whatever free space is left in that full height UL is put above that last Li.
And this effectively pushes, or pins, it to the bottom of its parent UL.
[COUGHS] I won't walk you through the CSS that you could use as a fallback to create a similar pinning effect.
But the gist of it is that you (could use display)table-cell to create equal height boxes.
And then add a good chunk of padding and Ems to the bottom of each of those boxes.
And use absolute positioning to pin the other row in the space left by that padding.
This isn't as nice as the Flexbox version, since you have to hard code that padding value.
And there's always the potential for overlaps when you use absolute positioning.
But it will look the same as the Flexbox version, just not as robust.
I also made use of auto margins on the wide view of the main nav by setting margin left to auto on the third link-- the throw a party link-- which pushes all the extra space in its line to its left edge.
So that it and everything following it gets pushed to the right side.
So without Flexbox most people would cheat and break this into two lists, which is less accessible and robust, again.
So hopefully you feel eager to try out some of these Flexbox tricks.
But some of you might be thinking, OK.
I see that I can use Flexbox as progressive enhancement right now, but why would I want to go to the trouble? After all the examples that I showed you were basically just cosmetic enhancements, and they might not be seen by a whole lot of your audience.
So is the extra work worth it? I say, yes.
I think you should learn and use Flexbox now for these reasons.
It's going to be an essential layout tool in the future, especially as responsive web design becomes more prevalent.
So it's better for your career to learn it now.
Get ahead of the competition.
The syntax is not going to change much at this point.
So what you learn now will still work later, and you'll have that skill ready to go for when it's needed.
In our field we're always having to add to our skill set, and sometimes make big shifts in the way that we do things.
I already told you about when I learned about CSS for layout, but it was a while before that when I first learned about CSS as a thing.
And for some reason, I can remember exactly where I was when I first heard about CSS.
And this is a nearly verbatim quotation of one of the things that I said to the person who's trying to convince me that CSS was the next big thing.
So, I have a distinct memory of defending font tags.
[COUGHS] This seemed like a perfectly logical viewpoint at the time.
And it did have some validity to it.
This seems like a perfectly logical viewpoint now.
And it definitely has validity to it.
I won't deny it.
But at some point our ever changing industry forces us to stop asking this question, because that new technology or new technique is no longer really new, and has now become standard and expected.
Just like learning CSS, or floats, or responsive web design, the pain was less if you learned it early when it was still somewhat new and not yet the way it's done, and gave yourself time to experiment with it.
The best way to learn Flexbox, of course, is to use it hands on.
I learned a lot more about Flexbox by building the demo site for this presentation.
I've already told you about some of the mistakes that I made and what I learned from that.
And I feel like I know it a lot better now.
Using Flexbox for small cosmetic enhancements-- like the progressive enhancement examples that I showed you-- may seem trivial.
But it's a really low risk way to try it and get used to how it works, how you write the syntax, how it operates in browsers.
And finally, I think you should start using Flexbox because it's fun.
You can read lots of articles on web design, and UX blogs about the little moments of delight that we can, and should be, giving our users through our work.
But what about giving ourselves little moments of delight through our work? There's no reason why we can't do both.
We should enjoy our jobs to get better at our jobs.
It might take a little longer to add on Flexbox as progressive enhancement.
But if it's a fun challenge and rewarding to see at the end, it's worth it.
Every once in awhile forget the rule that you only add something to the site if the browser metrics, ROI, test analytics, whatever, say it's worthwhile.
And add a bit of CSS because you think it's awesome, and you'll have fun writing it.
I had fun creating this presentation for you guys.
And if you want to download it and get links to related resources, head over to this URL on my blog.
Thanks very much.
[APPLAUSE] That was great.
Thank you very much.
Yeah, so there was a lot of great conversation in the past 40 minutes.
And one of the big questions that comes up in this topic, as it does in many times, is browser support.
Some people are just basically saying, you know, Flexbox seems like a lot to kind of absorb and learn.
It's very powerful, but I want to make sure that time investment is worth it.
So can you speak to, like, what the current mobile browser support is? And like, how well we can handle things there? Yeah, so the mobile browser support is very good, actually.
So, BlackBerry surprisingly has supported it for quite awhile now with the webkit prefix.
And Safari on iOS has supported it.
The newest version of Safari now supports the new syntax.
Previous versions have supported the 2009 syntax for several years now.
And the Android browser supports the 2009 syntax.
So, apart from-- and Opera Mini and mobile also support Flexbox.
So apart from IE mobile, you have very good support on and mobile.
Yeah, I think the can I use-- the can I use chart has like all these, like, partial things.
I mean, like, usually when you see those partial boxes you're like, hmm, not so sure.
But it's-- in Flexbox's case it's basically the 2009 spec is treated as partial.
And since that's handled strongly and you have support for that-- Right, yeah.
For the most part the change-- the differences between the syntax are just that.
Just syntax differences.
Flexbox mostly works the same in between those different syntaxes.
It's just that you use a different property name to do the same things.
And I guess the other question is-- and I guess this is mostly for Desktop IE 8 and 9, how do we handle that? Polyfills or-- what's the best approach? There used to be a Flexbox polyfill.
Last I checked, it hadn't been updated to the most current syntax.
That would be awesome once it is.
But I kind of see it just, like, with responsive web design where a lot of people will be feeding IE 6, 7, 8 a more simple layout anyway for those browsers.
So I kind of see it that same way with Flexbox.
Where you could be feeding those browsers just a more simple layout, and then be able to add on Flexbox for the other browsers that can handle it.
So it's just kind of another round of the same sort of thing, where we're taking versions of IE and saying, yes.
You will still get some basic styles.
You know, but not, perhaps, the full experience.
OK, one last question.
A few people noted they saw something around performance when it comes to Flexbox and concerns around the performance of using Flexbox.
Can you speak to that? I don't know a lot about the performance of Flexbox, so I'm not sure exactly how that-- OK.
I happened to write an article, like two days ago-- Oh, yeah? ---about-- on this topic.
The original concern came from an article in Smashing Magazine by the Financial Times guys that basically said they were using the old Flexbox.
They noted the layout times in Chrome dev tools were taking long.
And, anyways we did a bunch of research and found out that the new Flexbox is much faster.
And it's not too much of a concern.
---between the progressive enhancement and the performance, it's basically a solid way to be handling layout from now on.
I think so.
[APPLAUSE] (paul) All right.