The peculiar magic of flexbox and auto margins

Avatar of Robin Rendle
Robin Rendle on (Updated on )

In front-end development, there are often times when I know that I don’t know something. I might know enough to know what CSS to search for, but I have absolutely no idea how to use it or what the right syntax is. Somehow, in my head, there appears to be a filing cabinet that’s entirely empty, and when I try to look something up, all I find is an almost illegible sticky note instead.

One topic like this (which is an area I’ve sort of always known about but never really understood) is how auto margins and flexbox interact with one another.

Take this example for instance:

.parent {
  display: flex
}

.child {
  margin: auto;
}

What does this do again? I seem to recall there’s a bunch of nifty things you can do with it, and earlier this week, I half-remembered them after reading a great post by Sam Provenza from a while back that shows how auto-margins and flexbox work together. But I still didn’t quite get the concept even after reading that post, and it wasn’t until I started making demos of my own that it started to click.

In that post, Sam describes how margin: auto impacts flex items like so:

If you apply auto margins to a flex item, that item will automatically extend its specified margin to occupy the extra space in the flex container, depending on the direction in which the auto-margin is applied.

Let’s pick that apart a bit and say we have a simple parent div with a child div inside it:

<div class="parent">
  <div class="child"></div>
</div>

And let’s assume we’re using the following CSS to style those divs:

.parent {
  display: flex;
  height: 400px;
  background-color: #222;
}

.child {
  background-color: red;
  width: 100px;
  height: 100px;
}

The result is something like this:

See the Pen margin-auto: #1 by Robin Rendle (@robinrendle) on CodePen.

When we add margin-left: auto to the .child element like so:

.child {
  background-color: red;
  width: 100px;
  height: 100px;
  margin-left: auto;
}

…then we’ll see this instead:

See the Pen margin-auto: #2 by Robin Rendle (@robinrendle) on CodePen.

Weird, huh? The left-hand margin is pushing the parent so that the child is nestled up in the far right-hand corner. But it gets a little weirder when we set all margins to auto:

.child {
  background-color: red;
  width: 100px;
  height: 100px;
  margin: auto;
}

See the Pen margin-auto: #3 by Robin Rendle (@robinrendle) on CodePen.

It’s like we’re using a popular centering trick by setting justify-content and align-items to center because the child decides to rest in the center of the parent, both horizontally and vertically. Likewise, if we set margin-left and margin-top to auto, then we can let the flex item push itself into the bottom-right of the parent:

See the Pen margin-auto: #4 by Robin Rendle (@robinrendle) on CodePen.

When Sam says, “that item will automatically extend its specified margin to occupy the extra space in the flex container,” the way my empty filing cabinet brain interprets that is like so:

Setting the margin property on a flex child will push the child away from that direction. Set margin-left to auto, the child will push right. Set margin-top to auto and the child will push to the bottom.

After I write that down, it sounds so obvious to me now that it’s almost foolish but sometimes that’s what it takes to get a new concept to stick in my big dumb spongey noggin.

Why is this useful to know? Well, I think there are a few moments where justify-self or align-self might not get you exactly what you want in a layout where using auto margins gives you that extra flexibility to fine-tune things. A lot of demos I’ve seen out there, including the ones Sam made for her original post, mostly appear to be for aligning navigation items in a menu. So, pushing one item in that menu to the bottom or far right of a flex parent is certainly useful in those scenarios.

Anyway, I think this weird trick is important to remember, just in case.