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. Setmargin-left
toauto
, the child will push right. Setmargin-top
toauto
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.
The place this turned out to be really useful for me was when I wanted to center my content on the page, but also allow the content to grow larger than the parent. I started trying to type out what I meant, but in this case I think a codepen might be worth a thousand words…
align-items: center pushes the too-tall child off the top of the screen, while margin: auto still centers boxes that fit, but lets the child overflow if it grows too large
I already understood how
auto
margins worked in flexbox, however I never thought about what happens if you set all margins to auto.display: flex
on the parent +margin: auto
on the child is a really quick and easy vertical+horizontal center alignment technique.I think I’ll still go with
display: flex; justify-content: center; align-items: center;
as my main vertical+horizontal alignment technique though since it is less likely to break and it can all be placed into the same CSS declaration. Thismargin: auto
technique is an is an interesting alternative though.I never know which to choose – margin:auto or align/justify:center. After a phase of pure joy of “align/justify:center”, I lately decide more often for margin:auto. Don’t know why exactly. Maybe because it is shorter to write.
I didn’t really get to grips with flexbox until I worked through the excellent Flexbox Zombies. Ask me about my justify lasers! (Although this is a nice addition if I ever find issues with align-self)
There’s another one behind auto margins; in case we set flex-direction to column in a flex parent, we can use auto margins into a flex child instead of the vertically job of
align-self
property, it will do the same job ofalign-self
propery in the default scenario. for instance: setting margin-top to auto make the item push itself into the bottom.Fantastic explanation! I’ve seen this a few times on Stack Overflow but never fully understood it. Nice knowing there’s a simpler override than fumbling with the
-self
properties, particularly ifflex-direction
has you turned around to begin with.right, i so love grain controll like that. and margin:auto is a little bit sorter then item-self an is friend
What about defining margins only for the gaps. It is easy for horizontal layout but not with overflowing container using
flex-wrap: wrap
(the vertical margins).What a teasingly neat little thing to have missed. Thank you :D
Auto margins don’t behave strangely in Flexbox. They behave pretty much the same way they behave in Block flow (think about pushing your page content into the center, with margin auto left and right…). Anyway, the spec is pretty good on this, even has an example:
https://www.w3.org/TR/css-flexbox-1/#auto-margins
Thank you for this trick, I have been trying to grasp flexbox better, especially for stuff like headers, menus, etc. This is almost like a shorthand for the centering, and I will definitely be trying it out!
Great article, and now I understand this feature much better.
Quick typo fix, though: you wrote (4th paragraph from the end):
That last “top” should be “bottom”.