← All writing
Craft · · 6 min

display: flex, finally

On vertical centering after all these years, the three syntaxes still in the wild, and the IE11 bugs I hit in the first afternoon.

CSS Responsive Cross-Browser Compatibility

I wrote align-items: center on a client project last week and the thing centered vertically and I sat and looked at it for a second.

That sounds like a joke and it is a bit, but I mean it. I have written the position: absolute; top: 50%; -webkit-transform: translateY(-50%); transform: translateY(-50%) incantation so many times that my hands do it without consulting me. I’ve done the display table version. I’ve done the one where you set line-height equal to the height, which works on exactly one line of text and breaks silently on two.

One declaration! Anyway…

The C in CSS stands for compensating

I expected flexbox to let me build layouts I couldn’t build before. That’s how it gets talked about, and it’s sort of true but it’s not the main event.

What actually happened is that a bunch of my existing CSS turned out to be compensation, and I could delete it. The clearfixes went, because a flex parent contains its children by definition. The :last-child { margin-right: 0 } rules went, because I could use justify-content: space-between and let the gaps fall where they fall. The min-height I’d set on a sidebar to fake equal columns went, because align-items: stretch is the default and it just does that.

I took about 90 lines out of one component and added about 12. And none of the 90 were doing anything I’d have described as a hack at the time. They were just what CSS was.

A bunch of my existing CSS turned out to be compensation, and I could delete it.

Flexbox for dummies

There are a lot of flex properties and most of the tutorials introduce all of them at once, which I found genuinely confusing. In reality, the ones I reach for are maybe five.

display: flex on the parent, obviously. flex-direction when I want a column. justify-content for spacing along the main axis, the one people mean when they say flexbox does spacing. align-items for the cross axis, which is the vertical centering. And flex-wrap: wrap, without which a flex row will happily squash twelve items into a space meant for four rather than moving any of them to a second line, which surprised me the first time.

The one I’d flag as worth understanding properly rather than copying is the flex shorthand, because the shorthand and the longhand have different defaults and it catches people out.

columns.css
.col {
  flex: 1; /* === grow 1, shrink 1, basis 0% */
}

.col {
  flex-grow: 1; /* === grow 1, shrink 1, basis auto */
}
CSS

Those two look equivalent and are not. With basis: 0% the columns come out equal regardless of content, because the content size is taken out of the calculation before growing. With basis: auto the content size is the starting point, so a column with more text in it ends up wider. Both are useful and I have picked the wrong one at least four times.

Prefixes, prefixes everywhere

This is where I have to be careful, because “flexbox is ready” is a thing people say and it depends entirely on your support matrix.

There are three syntaxes in the wild from three stages of the spec. The old 2009 one with display: box, an awkward middle version from 2011 with display: flexbox that IE10 uses, and the current one. Autoprefixer handles the translation for you and does it well. That’s what makes this tractable at all, and I’d not attempt flexbox without it.

IE10 gets the middle syntax and mostly works. IE9 and below get nothing, so you need the layout to be tolerable without it, which in practice means writing the float version first and layering flex on top, or accepting a single column.

And IE11, the one that’ll actually cost you time, implements the right syntax with a set of real bugs. The two I hit in the first afternoon: flex-basis with box-sizing: border-box miscalculates when there’s padding, and a flex item with a percentage height inside a container without an explicit height collapses. There’s a well-known list of these floating around and it’s longer than you’d like.

Where to use it

Components, not pages. That’s the rule I’ve settled on for client work and it’s been holding up.

Inside a card, a nav, a media object, a form row, a footer with three columns: flexbox, no hesitation, with the float version as the fallback if IE9 is in scope. If something goes wrong it’s just one component, and if it degrades to stacked blocks in an old browser the page still reads fine.

For the overall page skeleton I’m still on floats and a grid framework, because that’s the thing where a failure is catastrophic rather than cosmetic, and because flexbox is honestly not the right tool for a two-dimensional page layout anyway. It’s one-dimensional by design. You can nest your way to a grid and it gets ugly fast.

There’s supposedly a proper grid spec coming that does two dimensions natively, and there’s an implementation behind a flag in IE which is a very funny place for the future to be living. I’ll believe it when I can use it.

It’s good to be flexible

The reason I’m slightly evangelical about this one, in a way I wasn’t about the build tool thing last post, is that this is a rare case of the new thing being less stuff rather than more. No dependency, no build step, no abstraction on top of abstraction. It’s a property in the language that replaces a whole category of workarounds.

That’s not the usual trade and I want to notice it when it happens.

Usual caveat: a month of real use, one person, one support matrix. If you’re on IE9 and below in volume then almost none of this applies to you yet and I’d sit tight. But go and try centering something.

Read similar posts
6 min

Container queries

Firefox shipped these two weeks ago, which means all three engines now have the thing everyone has been asking for since about 2013, and the headline everyone's using for it is not quite right.

7 min

Grid shipped today

Firefox on the Tuesday, Chrome on the Thursday, and after seven years of building page layout out of a property that was invented to wrap text around a photograph, we have a layout system that was designed as one.