Tags: flexbox



Designing Intrinsic Layouts by Jen Simmons

Alright, it’s time for the final talk of day one of An Event Apart in Seattle. The trifecta of CSS talks is going to finish with Jen Simmons talking about Designing Intrinsic Layouts. Here’s the description:

Twenty-five years after the web began, we finally have a real toolkit for creating layouts. Combining CSS Grid, Flexbox, Multicolumn, Flow layout and Writing Modes gives us the technical ability to build layouts today without the horrible hacks and compromises of the past. But what does this mean for our design medium? How might we better leverage the art of graphic design? How will we create something practical, useable, and realistically doable?

In a talk full of specific examples, Jen will walk you through the thinking process of creating accessible & reusable page and component layouts. For the last four years, Jen’s been getting audiences excited about what, when, and why. Now it’s time for how.

I’m not sure if live-blogging is going to work given the visual nature of this talk, but I’ll give it a try…

How many of us have written CSS using display: grid? Quite a few. How many people feel they have a good grip on it? Not so many.

Jen has spent the last few years encouraging people to really push the boundaries of graphic design on the web now that we have the tools to do so in CSS. But Jen is not here today to talk about amazing new things. Instead she’s going to show the “how?” The code is on labs.jensimmons.com.

Let’s look at laying out a header. You might have a header element with a logo image, the site name in an h1, and a nav element with the navigation. The logo, the site name, and the navigation are direct children of the parent header. By default we get everything stacked vertically.

<header role="banner">
    <img class="logo" src="..." alt="...">
    <h1>Site title</h1>
            <li><a href="...">Home</a></li>
            <li><a href="...">Episodes</a></li>
            <li><a href="...">Guests</a></li>
            <li><a href="...">Subscribe</a></li>
            <li><a href="...">About</a></li>

Why should we care about starting with semantic HTML? It matters for reusability and accessibility, but also for reader modes in browsers. These tools remove the cruft. If you mark up your content well, it will play nicely with reader modes. Interestingly, there are no metrics around how many people are using reader modes (by design). Mozilla has a product called Pocket that’s a “read later” app. It can also turn saved articles into a podcast for you. Well marked up content matters for audio playback.

Now let’s start applying some CSS. Fonts, colours, stuff like that. Everything is still stacking vertically though. It’s flow content. This can be our fallback layout. Now let’s apply our own layout. We could use float: left on the logo. Now we need some margins. We can try applying widths and floats to the h1 and the nav. Now we need a clearfix to get the parent to stretch to the full height of the content. It’s hacky. floats suck. But it’s all we had until we got flexbox. But even using flexbox for this kind of layout is a hack too. What we really need is CSS grid.

Apply display: grid to the header. Use Firefox’s dev tools to inspect the grid. Seeing the grid helps in understanding what’s going on. We’ve got three grid items in three separate rows. Notice that we don’t have margin collapsing any more. We can get rid of margins and use grid-gap instead. But we want is three columns, not three rows. We’ll try:

grid-template-columns: 1fr 1fr 1fr;

Looks okay. Not exactly the spacing we want though. We want the logo and the navigation to take up less space than the site name. We could translate our old percentage values into fr equivalents. 8% becomes 8fr. 75% becomes 75fr. 17% becomes 17fr. But the logo and the nav never shrink below their actual size. Layout isn’t working like we’re used to. The content will never get smaller than the minimum content size. So the amount of space assigned to each column is no longer linear.

Let’s change those fr units to percentages. Now we need to get rid of our gaps. But now when the layout gets small, everything squishes up. This is what we need breakpoints for. But now we can do something else. Let’s make the logo max-content. That column will now be the size of the logo. The other columns can remain `fr:

header {
    grid-template columns: max-content 3fr 1fr;

Let’s also define the last one—the navigation—as max-content. We can toss auto in for the middle content (the site name):

header {
    grid-template columns: max-content auto max-content;    }

Let’s layout the navigation horizontally. The best tool for this is flexbox. The li elements are the flex items. So the ul needs to be the flex container.

ul {
    display: flex;

Looking good. Let’s allow items to wrap onto another line:

ul {
    display: flex;
    flex-wrap: wrap;

Let’s change that navigation from max-content to auto so that it doesn’t get too long:

header {
    grid-template columns: max-content auto auto;   }

(How you want the navigation items to wrap determines whether you use flexbox or grid. Both are perfectly valid choices. There’s nothing wrong with using grid for the small stuff.)

Just look at how little code we need for this layout!

Let’s try a different layout. We’ll put the navigation on a new row.

header {
    grid-template-columns: min-content auto;
    grid-template-rows: auto auto

Let’s get the logo to span across both rows:

.logo {
    row-span: 2;

Need to finesse the alignment of the navigation? No problem. Play with align-self property on the nav element.

Again, look at how little code this is!

But these layouts are safe. We need to break out of our habits. What about disjointed text? Let’s take the h1. Apply some typography and colour. Also apply overflow-wrap: anywhere. Now the text can break within words.

We can take this further. But to do that, we have to wrap all of my letters in separate spans. Yuck!

Apply display: grid to the h1 that contains all those span children. Say grid-template-columns: repeat(8, 1fr) to make an eight-column repeating grid.

Let’s make it more interesting. We can target each individual letter with grid-column and grid-row. There are many ways to tell the browser where to place grid items. We can tell them the start lines. By default it will take up one cell.

Let’s add some images. Let’s rotate items. Place items wherever we want them. Mess around with the units to see what happens. Play with opacity when elements overlap. See the possibilities!

But, people cry, what about Internet Explorer? Use @supports

/* code for every browser */

@supports (display: grid) {
    /* code for modern browsers */

Set up a fallback outside the @supports block. Toggle grid on and enough in dev tools to see how the fallback will look. If this kind of thinking is new to you, please watch youtube.com/layoutland where Jen talks about resilient CSS.

Let’s try something else. Jen got an email announcement for an event. It had an interesting bit of layout with some text overlapping an image.

Mark up the content: some headings and images. By default the images are displayed inline. The headings are displayed as blocks.

Think about where your grid lines will need to go. How many lines will you need? How about setting your columns with 1fr 3fr 3fr 1fr? Now how many rows do you need? You define and the grid on the container and tell the items where to go. Again, it’s not much code. Tweak it. How about setting the columns to be 1fr minmax(100px, 400px) min-content? You have to mess around to see what’s possible. You can use all sorts of units for columns: fixed lengths (pixels, ems, rems), min-content, max-content, percentages, fr units, minmax(), and auto. Play around with the combinations.

Jen shows a whole bunch of her demos. Check them out. Use web inspector to play around with them.

And with that, the first day of An Event Apart Seattle is done!

Making Things Better: Redefining the Technical Possibilities of CSS by Rachel Andrew

The CSStastic afternoon of day one of An Event Apart in Seattle continues with Rachel Andrew. Her talk is Making Things Better: Redefining the Technical Possibilities of CSS. The description reads:

For years we’ve explained that the web is not like print; that a particular idea is not how things work on the web; that certain things are simply not possible. Over the last few years, rapid browser implementation of advances in CSS have given us the ability to do many of these previously impossible things. We can use our new powers to build the same designs faster, or we can start to ask ourselves what we might do if we were solving these problems afresh.

In this talk, Rachel will look at the things coming into browsers right now which change the way we see web design. CSS subgrids allowing nested grids to use the track definition of their parent; logical properties and values moving the web away from the physical dimensions of a computer screen; screen experiences which behave more like an app, or even paged media, due to scroll snapping and multidimensional control. By understanding the new medium of web design we can start to imagine the future, and even help to shape it.

I’m not sure if it even makes sense to try to live-blog a code talk, but I’ll give it my best shot…

Rachel has been talking about CSS at An Event Apart for over three years now. Our understanding of the possibilities of CSS has changed a lot in that time. Our use of floats for layout is being consigned to history. It’s no less monumental than the change from tables to CSS. Tableless web design often meant simplifying our designs. We were used to designing in a graphic design tool and then slicing it up into table cells. CSS couldn’t give us the same fine-grained control so we simplified our designs. It got us to start thinking of the web as its own medium. That idea really progressed with responsive web design.

But perhaps us CSS advocates downplayed some of the issues. We weren’t trying to create new CSS, we were just trying to get people to use CSS.

What we term “good web design” is based in the technical limitations of CSS. We say “the web is not print” when we see a design that’s quite print-like. People expect to have to hack at CSS to get it to do what we want. But times have changed. We have solved many of those problems (but that doesn’t mean we got all of them!).

Rachel spends a lot of time telling designers: you never know how tall anything is on the web. It used to be a real challenge to get the top and bottom of boxes to line up. We’d have to fix the height of the boxes. And if too much content goes in, the content overflows. Then we end up limiting the amount of content at the CMS side. We hacked around the problem. A technical limitation influenced our design, and even our content management. Then we got flexbox. Not only did the problem disappear, but the default behaviour is exactly what we struggled with for years: equal height columns.

How big is this box? You’ve seen the “CSS is awesome mug”, right?

Our previous layout systems relied on percentage lengths for widths. Those values had to add up to 100%, and no more. People tried to do the same thing with flexbox. People made “grid systems” with flexbox that gave widths to everything. “Flexbox is weird!”, people said. But the real problem is that flexbox is not the layout method you think it is. It’s for taking a bunch of oddly-sized things and returning the most reasonable layout for those things. It assigns space in a smart way. That solves the problem of needing to give everthing a width. It figures it out for you. If you decide to put widths on everything, you’re kind of working against flexbox.

We’re so used to having to hack everything in CSS, we had to take a step back with flexbox and realise that hacks aren’t necessary.

CSS tries to avoid data loss. That’s why the “CSS is awesome” text overflows the box. You don’t want the text to vanish. Visible overflow is messy, but it’s better than making some content disappear.

In the box alignment specification, there’s the concept of safe and unsafe alignment. Safe:

.container {
    display: flex;
    flex-direction: column;
    align-items: safe center;

You give the browser permission to align items to the start if necessary. But you can override that with unsafe:

.container {
    display: flex;
    flex-direction: column;
    align-items: unsafe center;

Overflow is going to happen. Now it’s up to you what happens when it does.

The “content honking out of the box” problem described in the “CSS is awesome” meme is now controlled with min-content:

width: min-content;

The box expands to encompass the widest content.

You have many choices. But what if the text isn’t running left to right? It might not be a problem we run into for English text. For years, CSS had that English-centric assumption baked in. Now CSS has been updated to not make that assumption. The web is not left to right. Flexbox and grid take an agnostic approach to the writing mode of the document. There’s no “top”, “bottom”, “left” or “right”. There’s “start”, “end”, “inline” and “block”. Now we have a new spec for logical properties and values. It maps old physical values (top, bottom, etc.) to the newer agnostic values.

So even if you use writing-mode to flip direction, width is still a width. Use inline-size instead of width and everything keeps working: the width maps to height when you apply a different writing-mode value. Eventually we’ll use those flow-relative values more than the old values. Solutions need to include different writing modes.

There is no fold. We’ve said that for years, right? But we know where the fold is. We’ve got viewport units that represent the width and height of the browser viewport. We can start to make designs that make use of the viewport. You can size a screen full of images exactly to fit the visible space. Combine it with scroll-snap to get the page views to snap as the user scrolls. You get paged layout. That’s interesting for Rachel because she’s used to designing for paged layout in print versus continuous layout on the web.

What’s next for CSS grid? Grid layout has been the biggest problem-solver of recent years. But that doesn’t mean it has solved all the layout problems. New problems appear as we start to work with CSS grid. We often end up nesting grids. But the nested grids don’t have any knowledge of one another. We’re back to: you never know how tall things are on the web. We need a way to have a relationship. Some kind of, I don’t know, subgrid.

You could use display: contents. It removes a box from the visual display allowing grandchildren to act like children. The browser support is good, but there’s a stonking accessibility bug so don’t use it in production. Also you can’t apply visual styles to anything that’s got display: contents on it. But grid-template-rows: subgrid will solve this problem. The spec is in a good shape. We’re waiting for the first browser implementations.

You will hit problems. Find new technical limitations. It’s just that we can’t do that stuff yet. We get the new stuff when we create it. Write up the problems you come across.

We’re finding the edges. Rachel is going to share her problems.

Rachel wants to put some text into her image grid. No problem. But then if there’s too much text, it might not fit in a height-restricted row. We can adjust the row to not be height-restricted, but then we lose the nice viewport-fitting layout.

In continuous media—which is what the web is—content inside multicol gets longer and longer. You can fix the height of the container but then the columns get created horizontally. What if you could say, I want my multicol container to be, say 100vh high, but if the content overlows, create a new 100vh high container below. Overflow in the block dimension. Maybe that’ll be in the next version of the multicol spec.

Multicol doesn’t solve Rachel’s image grid situation. What she needs is a way for the text to fill up a box and then flow into another box. The content needs to be semantically marked up—not broken into separate chunks for layout—and we want the browser to figure out where to break that content and fill up available space.

It comes as a surprise to people that a lot of paged media—books, magazines—are laid out with CSS. It’s in the paged media module. Prince is a good example of a user agent that supports paged media. There’s the concept of a page box: a physical page into which content can go. You get to define the boxes with physical dimensions like inches or centimeters. You create a bunch of margin boxes with generated content. Enough pages are created to hold all the content. You create your page model and flow the content through it.

Maybe apps and websites with defined screens are not that different from paged contexts. There have been attempts to create CSS specs that would allow this kind of content-flowing behaviour. CSS regions was one attempt. There was -ms-flow-into and -ms-flow-from in the IE and Edge implementations. You had to apply -ms-flow-into to an iframe element.

Regions needs ready-prepared boxes for the content to flow into. But how can you know how many boxes to prepare in advance? You don’t know how big things will be on the web. Rachel has been told that there’s nothing wrong with the CSS regions spec because you can define a final bucket for all leftover content. That doesn’t seem like a viable solution.

CSS regions predated CSS grid and didn’t take off. Now that we’ve got grid, something like regions makes a lot of sense.

Web design has been involved in a constant battle with overflow. Whether it’s overflowing boxes, or there (not) being a fold, or multicol layout. Rachel thinks we can figure out a way to get regions to work. Perhaps regions paved the way for something better. Maybe it was just ahead of its time. There are a lot of things hidden away in CSS specs that never made it out: things that didn’t make sense until more advanced CSS came along.

Regions—like multicol—relies on fragmentation. Ever tried to stop a heading behind the last thing on a page in a print stylesheet? We need good support for break-inside, break-before, and break-after.

We create new things to solve problems. Maybe you don’t see the value of something like regions, but I bet there’s been something where you thought “I wish CSS could do this!”.

Rob wrote up a problem that he had with trying to have a floated element maintain its floatiness inside a grid. He saw it as a grid problem. Rachel saw it as an exclusions problem. Rob’s write-up was really valuable to demonstrate the need for exclusions. Writing things up is hugely valuable for pushing things forward. Write up your ideas—they’ll show us the use case.

Ask “why can’t I do that?” Let’s not fall into the temptation of making things grid-like just because we have CSS grid now. Keep pushing at the boundaries.

Many of things Rachel has shown—grid, exclusions, regions—were implemented by Microsoft. With Edge moving to a Chromium rendering engine, we must make sure that we maintain diversity of thought in the standards process. Voices other than those of rendering engines need to contribute to the discussion.

At a W3C meeting or standards discussion, the room should not be 60-70% Googlers.

More than ever, the web needs diversity of thought. Rachel isn’t having a dig at Google. This isn’t a fight between good and evil. It’s a fight against any monoculture. So please contribute. Get involved. Together we can work for the future of the web platform.

Fit For Purpose: Making Sense of the New CSS by Eric Meyer

Time for even more CSS goodness at An Event Apart Seattle (Special Edition). Eric’s talk is called Fit For Purpose: Making Sense of the New CSS. Here are my notes…

Eric isn’t going to dive quite as deeply as Rachel, but he is going to share some patterns he has used.

Feature queries

First up: feature queries! Or @supports, if you prefer. You can ask a browser “do you support this feature?” If you haven’t used feature queries, you might be wondering why you have to say the property and the value. Well, think about it. If you asked a browser “do you support display?”, it’s not very useful. So you have to say “do you support display: grid?”

Here’s a nice pattern from Lea Verou for detecting support for custom properties:

@supports (--css: variables)

Here’s a gotcha:

@supports (clip-path: polygon())

That won’t work because polygon() is invalid. This will work:

@supports (clip-path: polygon(0 0))

So to use feature queries, you need to understand valid values for properties.

You can chain feature queries together, or just pick the least-supported thing you’re testing for and test just for that.

Here’s a pattern Eric used when he only wanted to make text sideways, but only if grid is supported:

@supports (display: grid) {
    @supports (writing-mode: sideways-lr) {

That’s functionally equivalent to:

@supports (display: grid) {
@supports (display:grid) and (writing-mode: sideways-lr) {

Choose whichever pattern makes sense to you. More to the point, choose the pattern that makes sense to your future self when you revisit your code.

Feature queries need to work together with media queries. Sometimes there are effects that you only want to apply on larger viewports. Do you put your feature queries inside your media queries? Or do you put your media queries inside your feature queries?

  • MOSS: Media Outside Support Statements
  • MISO: Media Inside Supports Object

Use MOSS when you have more media switches than support blocks. Use MISO when you only have a few breakpoints but lots of feature queries.

That’s one idea that Eric has. It’ll be interesting to see how this develops.

And remember, CSS is still CSS. Sometimes you don’t need a feature query at all. You could just use hanging-punctuation without testing for it. Browsers that don’t understand it will just ignore it. CSS has implicit feature queries built in. You don’t have to put your grid layout in a feature query, but you might want to put grid-specific margins and widths inside a feature query for display: grid.

Feature queries really help us get from now to the future.


Let’s move on to flexbox. Flexbox is great for things in a line.

On the An Event Apart site, the profile pictures have social media icons lined up at the bottom. Sometimes there are just a few. Sometimes there are a lot more. This is using flexbox. Why? Because it’s cool. Also, because it’s flexbox, you can create rules about how the icons should behave if one of the icons is taller than the others. (It’s gotten to the point that Eric has forgotten that vertically-centring things in CSS is supposed to be hard. The jokes aren’t funny any more.) Also, what if there’s no photo? Using flexbox, you can say “if there’s no photo, change the direction of the icons to be vertical.” Once again, it’s all about writing less CSS.

Also, note that the profile picture is being floated. That’s the right tool for the job. It feels almost transgressive to use float for exactly the purpose for which it was intended.

On the An Event Apart site, the header is currently using absolute positioning to pull the navigation from the bottom of the page source to the top of the viewport. But now you get overlap at some screen sizes. Flexbox would make it much more robust. (Eric uses the flexbox inspector in Firefox Nightly to demonstrate.)

With flexbox, what works horizontally works vertically. Flexbox allows you to align things, as long as you’re aligning in one direction. Flexbox makes things springy. Everything’s related and pushing against each other in a way that makes sense for this medium. It’s intuitive, even though it takes a bit of getting used to …because we’ve picked up some bad habits. To quote Yoda, “You must unlearn what you have learned.” A lot of the barrier is getting over what we’ve internalised. Eric envies the people starting out now. They get to start fresh. It’s like when people who never had to table layouts see code from that time period: it (quite rightly) doesn’t make any sense. That’s what it’s going to be like when people starting out today see the float-based layouts from Bootstrap and the like.


That’s going to happen with grid too. We must unlearn what we have learned from twenty years of floats and positioning. What makes it worth is:

  1. Flexbox and grid are pretty easy to get used to, and
  2. It’s amazing what you can do!

Eric quotes from an article called How We adopted CSS Grid at Scale:

…we agreed to use CSS Grid at the layout level and Flexbox at the component level (arranging child items of components). Although there’s some overlap and in some cases both could be used interchangeably, abiding by this rule helped us avoid any confusion in gray areas.

Don’t be afraid to set these kind of arbitrary limits that aren’t technological, but are necessary for the team to work well together.

Eric hacked his Wordpress admin interface to use grid instead of floats for an activity component (a list of dates and titles). He initially turned each list item into a separate grid. The overall list didn’t look right. What Eric really needed was a subgrid capability, so that the mini grids (the list items) would relate to one another within the larger grid (the list). But subgrid doesn’t exist yet.

In this case, there’s a way to fake it using display: contents. Eric made the list a grid and used display: contents on the list items. It’s as though you’re saying that the contents of the li are really the contents of the ul. That works in this particular case.

The feature queries for that looked like:

@supports (display: grid) {
    @supports (display: contents) {

Eric is also using the grid “ASCII art” (named areas) technique on his personal site. This works independent of source order. For that reason, make sure your source order makes sense.

Using media queries, Eric defines entirely different layouts simply by using different ASCII art. He’s switching templates.

For a proposed redesign of the An Event Apart site, Eric used CSS grid as a prototyping tool. He took a PDF, sliced it up, exported JPGs, and then used grid to lay out those images in a flexible grid. Rapid prototyping! The Firefox grid inspector really helps here. In less than an hour, he had a working layout. He could test whether the layout was sensible and robust. Then he swapped out the sliced images for real content. That took maybe another hour (mostly because it was faster to re-type the text than try to copy and paste from a PDF). CSS makes it that damn easy now!

So even if you’re not going to put things like grid into production, they can still be enormously useful as design tools (and you’re getting to grips with this new stuff).

See also:

100 words 033

Charlotte came up with a nifty trick that combines two different techniques she’s been working with.

The first building block is the pattern of using checkboxes, labels, and the :checked pseudo-class to create progressive disclosure toggles without JavaScript. There’s just one caveat with that technique though—the item being toggled must appear after the trigger label in the source order of the markup.

Enter the second building block: flexbox. With flexbox, we’re no longer at the mercy of the source order in our markup. By using flex-direction: column-reverse, the progressive disclosure trigger can be displayed after the item being toggled.


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:

<div role="main">
<p>This is the main content</p>
<nav role="navigation">
<p>This is the navigation</p>

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>
<li><a href="#">foo</a></li>
<li><a href="#">bar</a></li>
<li><a href="#">baz</a></li>

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.