float: left is a layout system

#css #cross-browser-compatibility

Float was designed so you could put an image in an article and have the text go around it. That’s it. That’s the use case. It’s in the spec, it’s what magazines do, and it’s what the property is for.

And yet we have built the entire visual web on top of it.

I don’t say that as a gotcha. I say it because I spent a chunk of last week debugging the three-column layout on my own portfolio, where the third column had dropped to a new line at exactly one browser width. Somewhere around the hour mark I thought, “None of us chose this.”

Every one of us inherited a situation where the only tool that reliably puts one thing next to another is a text-wrapping property from nearly 20 years ago. And we’ve all kind of agreed to pretend that’s normal.

Bad parenting in HTML land

Nobody expects float to take the element out of the flow but it does, which means its parent stops accounting for its height. You get a container with 3 columns in it and a computed height of 0, and the next section slides straight up underneath.

The fix is to make the parent contain the floats again. There are roughly four ways I’ve done this, in order of how long ago I stopped doing them.

The first is an empty div with clear: both at the end. It works and it’s what I was taught. It’s also a piece of markup that exists purely to serve a stylesheet, which should feel bad and after a while does.

The second is overflow: hidden on the parent, which establishes a new block formatting context and makes it contain its floats. One property! Super tidy. And then six months later you need a dropdown to hang outside that container and it gets guillotined. You spend a while confused until you find the overflow: hidden you wrote and don’t remember why.

The third is the clearfix, which is the one all the cool kids are using now:

_utilities.scss
.clearfix:after {
  content: "";
  display: table;
  clear: both;
}
CSS

It’s three declarations and a generated pseudo-element whose entire job is to be an invisible thing at the end of the box that clears. It works everywhere back to IE8. There’s a longer version with *zoom: 1 for IE7, which I am choosing to believe nobody still needs.

The fourth, which I’ve come around to, is to just not have a .clearfix class in the markup at all. I @include it in the component that needs it so the HTML doesn’t have to know about the plumbing.

Column, why won’t you column?

The other classic is the one that ate my week. Floats have no idea that they are a row. They’re a sequence of boxes finding somewhere to sit. If a row of 3 columns at 33.333% each adds up to 100.001% because of subpixel rounding, the third one doesn’t fit.

So you round down and now you’ve got a gap on the right. Or you use a grid framework, which is doing the same rounding for you and has a bunch of :last-child rules to mop up the margins. Or you go percentages with negative margins on the row, which is what most of them actually do under the hood.

And equal-height columns are famously not a thing.

You get faux columns with a repeating background image on the parent. That’s a technique with a name and tutorials and everything, and it’s also a background image cosplaying as a layout. Or you go display table. Or (and I have done this more than once) you set a min-height and hope the content behaves.

Flexbox though

I know, I know. Flexbox exists and it does all of this properly. It has align-items and it doesn’t need clearing because the parent knows its children are children.

I’ve used it on exactly one thing, a little helper page I built for myself where the only browser that would ever open it was mine. It was beautiful. Amazing to see align-items: center after doing the position: absolute; top: 50%; transform: translateY(-50%) dance.

But browser support right now is not good enough for client work, as much as I’d like it to be. There are three syntaxes floating around from different draft versions. Old Firefox does one, old iOS Safari does another with -webkit-box, IE10 does -ms-flexbox, and IE9 and below do nothing at all.

There are known bugs in IE11 around flex-basis and min-height that I don’t fully understand yet. You can paper over a lot of it with a preprocessor mixin or Autoprefixer and people do. I think that’s a reasonable bet on a personal project.

On a site for the general public, IE9 and below still show up in the analytics in numbers you can’t wave away so it isn’t a bet I’d make with somebody else’s layout. So it’s floats, clearfix, negative margins, and the mild indignity of it.

No conclusion, really

I’m not sure this post has one and maybe that’s fine.

I spent the last year thinking clearfix was a normal part of knowing CSS, like it was a technique instead of a scar. I keep turning that over. It’s in every framework and it’s in the boilerplate and nobody flags it as strange.

But it is strange! We are all serving an invisible generated pseudo-element to patch the side effects of a text-wrapping property. That’s a really odd thing to have converged on. We got there because there was no alternative for as long as we’ve been building websites and so it stopped registering.

I don’t think there’s a lesson here beyond noticing it. I feel like a decent amount of what I “know” about CSS is going to turn out to be like clearfix. It isn’t knowledge so much as a constraint I’ve been pressed up against for long enough that I mistook it for the way things are.

Read similar posts

View posts by tag

#accessibility #agency #ai #careers #cross-browser-compatibility #css #culture #debugging #documentation #ecommerce #forms #git #html #images #javascript #performance #php #privacy #scss #security #shopify #small-print #tooling #typography #wordpress