This is a spin-off post from my article over on HTML5Hub: “Centering All The Directions. In that article, I addressed a wide range of various techniques and “hacks” (more on that term below) for accomplishing centering of content, specifically the ever-elusive vertical centering. I made some assertions in that article which seem to be ruffling the feathers of some people, so I figured I might as well explain myself in more detail.

Define: “hack”

But first, before we get there, I need to explain my definition of “hack”, as it seems to be at the root of some of the disagreement.

In the context of accomplishing some particular X task with Y tool (some CSS feature), I call it a “hack” if the desired outcome is arrived at indirectly as a side-effect (or at best, a minor part) of some other feature.

So, what’s not a hack? <center> is not a hack. It’s old school and busted and totally deprecated and kills little unicorns every time you use it. But at least it did what it said on the package. text-align:center is also not a hack, at least when you use it to horizontally center inline content like text. But even text-align:center becomes a hack when you start using it on block-level elements in peculiar side-effect ways to accomplish your goal. That’s not what it’s for, that’s why it’s called “text align” — not so you can align your icons.

margin:auto and margin:-XYZpx tricks are also hacks when used to try to create the illusion of “centering”. Why? Because you’re not styling the content itself, you’re styling the space around the content to try and get that content where you want it. That’s indirect. That’s a “hack”.

Tool, meet task, task meet tool

Here’s another way of thinking about what I mean by “hack”. Let’s consider you have some piece of software that does a million things, and super powerful, but it’s really memory and CPU hungry. Then, let’s imagine you have (or conceive) of another tool, one which does just one of those million tasks, and does it really well, and does it with far less pomp-and-circumstance, far less complication, far less memory and CPU hogging, etc.

Now, if given the choice between the two tools, for the one specific X task, and you choose (unnecessarily) to use the much more complex tool to do the small narrow task, I call that “hacking” the tool. Disagree with my terminology? Fine. This is my definition. And it’s my blog post. :)

The cliche that applies is: “using a sledgehammer to drive in a tiny pushpin”. In other words, just because a tool can do a task, doesn’t mean that tool is the right tool for the job.

On the flip side, if all you know about (or prefer) is the sledgehammer, you’re going to go around looking for ways to use it because that’s your only tool. Again, applicable cliche: “when all you have is a hammer, everything looks like a nail”.

This is not a healthy way to think about our use of technology. That’s what I’m trying to get us past.

CSS hacks

For some reason, developers seem enamored and almost religiously attached to their various chosen CSS hacks for any given task. I’m not quite sure what the psychological issue here is, but I liken it to Stockholm Syndrome: you’ve been held hostage by these hacks for so long that you start to love and cherish them.

It’s time to put down the hacks and walk away. Seriously. Put it down. No.. put it down.

Define: “layout” vs. “positioning”

Another definitional problem that seems to be at play is that developers seem to conflate the idea of “layout” with “positioning”. Let me try to share my definition and dispel those confusions.

Layout, or more completely, “Layout Structuring” is, by my definition, the task of describing how multiple pieces (yes, plural) of content fit together to create a full page or app. Layout structuring deals with things like content “flow”, re-layout changes, etc. When element A changes its dimensions, element B is often affected, when they two of them are related to each other by “layout structuring”. When the viewport size changes on a browser, or the device is rotated and the screen orientation changes, layout structuring is what controls how, if at all, the content will respond to those conditions.

Positioning, on the other hand, is describing how to take a single element and put it somewhere specific, somewhere that perhaps it might not normally have been if you didn’t specifically “position” it. That’s not just position:absolute, btw. But certainly that’s one key example of it.

Centering

So what about the task of “centering” some element inside another element? Is that “layout structuring” or is that “positioning”? I say it’s “positioning”.

Why does that classification matter? Because it means, IMO, that using a layout structuring tool to do a positioning task is hack’ish. Vice versa, using a positioning tool for layout structuring is also a regrettable hack.

We can agree that using position:absolute type techniques to layout all the pieces of content on our page is usually not a good idea, right? Remember how we all used to do that, and then we realized that most of the time that wasn’t very effective? Yeah, I remember it, too.

So the same reasoning tells us that tools for layout structuring are not well-suited for positioning tasks.

<table>

Remember like a decade ago when a bunch of self-righteous standardistas ran around slapping the hands of web developers who used <table> based layout? Why?

Well, because <table> was intended to be used as a way to structurally layout a grid of data (that’s why the “td” in <td> stands for “table data”). Was it designed for laying out whole pages of elements, most of which were not data? NO!

Could you? Sure. But should you? Most of us agree not.

And btw, when the CSS gurus came along years later and added display:table type stuff, I wasn’t fooled, but many of you were. Many of you thought, “oh, cool, tables without the <table>s.” I shook my head then, and I do so now.

No matter what strawman you try to construct, you can’t convince me that display:table is somehow not <table>. It is, it’s just a pig with some lipstick on it.

Does that mean tables are evil? NO! Use them for laying out grids of data, by all means. And use the nice CSS features to help you style those grids properly. But don’t try to pretend that we can hijack the terms “table” and “table-cell” in CSS and somehow magically that’s not the same thing as the markup for tables. That’s just shifting the presentation control to the CSS from the markup, which is a very good thing!

But don’t try to argue that we should use one of the side-effects of tables, the fact that table cells have nice vertical centering capabilities, as our “standards solution” for centering content vertically. The fact that I can do that with CSS doesn’t make it any better than if I stuck <table><tr><td>.. into my markup and then defended it by saying, “Oh, it’s cool. I’m totally just using the tables for vertical centering. No worries”.

That’s as flimsy a defense as it gets.

Using tables for centering is a hack. Plain and simple.

Flexbox

If you haven’t heard, the (supposed) new savior of CSS is flexbox. It’s cited time and again as the silver bullet for every pain point you can imagine. “It slices, it dices, it makes you coffee in the morning.”

When I examined CSS centering, I explicitly left flexbox out of the main article, but covered in a comment what my thoughts were on it, with respect to using it to “solve” centering issues.

Boiled down: I think flexbox is a giant, complex, super-powerful hammer-of-Thor type tool being used to thread a tiny needle… if all you use it for is centering. Remember layout vs. positioning?

Flexbox was designed for layout structuring, mostly as a way to solve the many complexities of responsive layout. And it’s really good at that task. That complex, difficult task of shifting items around and resizing and re-orienting them smoothly and gracefully as people spin their tablets around on their fingers like basketballs.

Here’s the thing: flexbox does have some centering capabilities. But they are offshoots of much more complex layout-structuring concerns.

Using flexbox asks you to think about more complex mental-model concepts like a main axis vs. a cross-axis, and lines of items, and implicit flex items, and such. There’s a lot to it. Want to understand it fully? Chris Coyier has a fantastic “Complete guide to flexbox” article. Go read it!


UPDATE: Saw this link tweeted today: CSS Box Alignment Module, a draft spec for CSS3+ which self-describes an attempt to make centering, especially vertical centering, be served by “a cohesive and common box alignment model to share among all of CSS.”

While the spirit of that effort is nice, I encourage you to go read a few paragraphs of that document, and see if you can figure out how to easily center (horizontally and vertically) one element inside another element. I’ll wait while you go try that.

..

Back? Yeah, I didn’t figure it out either. Far too complicated, IMO.


So… CAN it accomplish the simple task of centering one element inside another parent element? Yes. But that’s not even remotely what that tool is supposed to be for and doesn’t even scratch the surface of its complexity.

You’re trying to use a layout-structuring tool for a positioning task. Sound familiar? Yeah, because that’s exactly what using tables for positioning is. Plainly: both are hacks for centering/positioning.

Not-a-hack plz?

Can we get something that’s not a hack, that’s not some side effect of some much more complex tool (that’s designed to be) used for fundamentally different sorts of tasks?

I proposed one in that other article:

#container { content-positioning:center center; .. }
#child { content-positioning-anchor:center center; .. }

<div id="container">
   <div id="child">Hello World</div>
</div>

Simply, content-positioning controls the vertical and horizontal positioning of its child element(s). And then content-positioning-anchor on the child element(s) controls where the registration point is on the content element for that positioning.

The snippet above says “put the center of my content at the center of the container.” Could it get any more semantic and simple than that?

Moreover, this gives us the freedom to do things which tables and flexboxes cannot, at least not without more hacks like abusing padding and margins. Say I want to position some item 10px off-center? Easy, I use these features along with the CSS calc(50% - 10px).

Try doing that without crazy hacks in flexbox and tables. Good luck.

</rant>

Tables and flexboxes are great… for what they’re intended for. They’re just the wrong tool for doing simple content positioning/centering. We need a better more suitable tool for that.

We definitely don’t need to keep holding onto our hacks like life-rafts in the middle of a raging ocean storm.

Hacks? Let’s get some better standards.

This entry was written by getify , posted on Friday August 02 2013at 12:08 pm , filed under Misc and tagged , , , . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

5 Responses to “Tables & Flex: Not the centering you’re looking for”

  • Juan says:

    I think this is a very good explanation of why a new CSS property would be desirable, although the focus on “centering” may be closing the door for more positioning options.

    As someone mentioned in a comment in another of your posts, the parent element doesn’t really need any new properties. The child element could decide which point inside it is the one that’s used for the positioning instead of forcing it to be the top left corner of the element. That’s why I think a position-origin property would be really useful.

    /* this centers the element */
    #element {
      position: absolute;
      top: 50%;
      left: 50%;
      position-origin: center center;
    }
    

    position-origin would not only allow for easy centering of an element, but also solve other use cases like aligning the center child element to a corner of the parent element. Think about the typical lightbox with an Apple-style close button (think http://images.apple.com/support/assets/images/assistant/shared/removeapp.gif).

    #element {
      position: absolute;
      top: 0;
      right: 0;
      position-origin: center center;
    }
    

    Examples: http://i.imgur.com/SCwGTxY.jpg

    It also introduces only one new concept. The rest is entirely based on what’s already in CSS.

  • getify says:

    @Juan I like your suggestion. As I mentioned on twitter, I was just worried about “hijacking” top/left and possibly having unintended side-effects compat-wise. We probably wouldn’t, but I wanted to be safer and suggest a more explicit opt-in to this new “thing”. If we don’t need the opt-in, the content-origin (or “anchor” or whatever we call it) is fine by itself, and that’s great! :)

  • getify says:

    More evidence that display:table is mostly just a hack: to center a <video> element horizontally, using margin:0px auto, you have to, for some crazy reason, put display:table on the <video> itself.

    Yeah, that’s right, you don’t put the table-CSS signal on the parent to get the centering of its content, you have to make the <video> (the content itself) act like a table so it can somehow center itself properly. display:block and display:inline-block don’t work. Only display:table works. A true WTF hack.

    UPDATE: this may not be true anymore. It was true awhile back when I worked on a project with a video in it. Just re-tested and Chome/Firefox both seem to center the video if it’s display:block. Guess I can go fix my code and take out the table-CSS hacks.

  • Juan says:

    Ok I exchanged a very interesting couple of tweets with a member of the CSSWG and I have some good news and some bad news.

    The good news is that we’re possibly getting ways of aligning edges of one node to edges of another.

    The bad news is that I don’t think we’re getting anything for centering. But I have to say I’m OK with left: 50%; top: 50%; transform: translate(-50%, -50%);. It’s almost the same as my previous proposal.

Leave a Reply

Consider Registering or Logging in before commenting.

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.