Re-flex
I was in Minnesota last week for An Event Apart Minneapolis. A great time was had by all. Not only were the locals living up to their reputation with Amy and Kasia demonstrating that Kristina isn’t an outlier in the super-nice, super-smart Minnesotan data sample, but the conference itself was top-notch too. It even featured some impromptu on-stage acrobatics by Stan.
A recurring theme of the conference—right from Zeldman’s opening talk—was Content First. In Luke’s talk it was more than a rallying cry; it was a design pattern he recommends for mobile: content first, navigation second. It makes a lot of sense when your screen real estate is at a premium. You can see this pattern in action on the Bagcheck mobile site (a button at the top of screen is simply a link that leads to the fragment identifier for the navigation at the bottom).
Later on, Eric was diving deep into the guts of the CSS3 flexible box layout module and I saw an opportunity to join some dots.
Let’s say I’ve got a document like this with the content first and the navigation second:
<body>
<div role="main">
<p>This is the main content</p>
</div>
<nav role="navigation">
<p>This is the navigation</p>
</nav>
</body>
Using box-orient:vertical
and box-direction:reverse
on the body
element, I can invert the display of those two children from the order they appear in the source:
body {
display: box;
box-orient: vertical;
box-direction: reverse;
}
If I wrap that in a media query, I can get the best of both worlds: content first, navigation second on small screens; navigation first, content second on larger viewports:
@media screen and (min-width: 30em) {
body {
display: box;
box-orient: vertical;
box-direction: reverse;
}
}
Works a treat (once you include the necessary -webkit
and -moz
prefixes).
I thought I’d take it a bit further. Suppose the navigation has a list of links:
<nav role="navigation">
<p>This is the navigation.</p>
<ol>
<li><a href="#">foo</a></li>
<li><a href="#">bar</a></li>
<li><a href="#">baz</a></li>
</ol>
</nav>
I could use flexbox to lay those items out horizontally instead of vertically once the viewport is large enough:
@media screen and (min-width: 30em) {
[role="navigation"] ol {
display: box;
box-orient: horizontal;
}
[role="navigation"] li {
box-flex: 1;
}
}
Here’s the weird thing: in Webkit—Safari and Chrome—the list items reverse their direction: “baz, bar, foo” instead of “foo, bar, baz.” It seems that the box-direction
value of reverse
is being inherited from the body
element, which I’m pretty sure isn’t the right behaviour. But it can be easily counteracted by explicitly declaring box-direction: normal
on the navigation.
What’s a little trickier to figure out is why Firefox is refusing to space the list items equally. I’ve put a gist on Github if you want to take a look for yourself and see if you can figure out what’s going on.
Update: You can see it in action on JSbin (resize the view panel).
The new CSS3 layout modules and responsive design could potentially be a match made in heaven …something that Stephen has been going on about for a while now. Check out his talk at Mobilism earlier this year.
You’ll notice that he’s using a different syntax in his presentation; that’s because the spec has changed. In my example, I’m using the syntax that’s currently supported in Webkit, Gecko and Internet Explorer. And, as Eric pointed out in his talk, even when the newer syntax is supported, the older vendor-prefixed syntax won’t be going anywhere.