Blog

Front End Development topics with a touch of humor

Center Something in a Div

Harder than one might think

October 7, 2020


One undisputable fact is that all front-end developers love CSS. In a world where drag-n-drop page builders exist, where most tasks can be achieved with a swipe of the finger or tap of a button, having to type in a line of code and refresh desperately is almost too much fun to cope with...

CSS, in the technical terminology of skill acquisition, falls into the category of easy-at-first-but-maddeningly-and-seemingly-intentionally-difficult later. I mean, do you enjoy having to target an element nested five deep with like five weirdly-named classes on it? I don't.

But we struggle on, we learne. Some of these lessons may seem obvious to us now, but not to a beginner. It may be worth revisiting some of these...

CSS Tricks.

First, a few ground rules

Have you ever read a CSS blog and the examples look easy to follow, but then you tried to do it yourself and nothing worked at all? I certainly remember that experience. And part of the issue is that the presenter never shared their setup. Let's not make that same mistake!

Center in a div

            Setup: 
            1 div
            1 box-shaped div within the div, which looks like a box because I
            have set the height and width and added a border. Otherwise, the 
            div would be invisible and extend all the way to the end of the 
            page.

            <style>
            .parent {
                height: 200px;
                border: 4px dotted black;
            }
            .box {
                /* padding: 50px; */
                border: 4px solid black;
                height: 100px;
                width: 100px;
            }
            </style>

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

The box can be centered by adding a single line to its properties:

 
        margin: 0 auto;
        

What does that even mean and why does setting the margins on a div center it? First, let's break down the setting. The css property margin: 0 auto is a shorthand expression for:

            margin-top: 0;
            margin-right: auto;
            margin: bottom: 0;
            margin-left: auto; 
        

That's a lot of typing for one widdle box. We often have the situation where the top and bottom margin are the same, and the left and right margins are the same. Notice the order I wrote; it's important. Also, if all the margins are the same, you could just write something like:

            margin: 25px;
        

This sets top, right, bottom, and left margins the same.

On the other hand, if you want to set all four margins different, but in one line, you can do that: just remember the order top, right, bottom, left. It's counterclockwise, in case you grew up in a completely digital world.

            margin: 20px 0 10px 200px;
        

But back to margin: 0 auto, an enigmatic declaration you will see in thousands of legacy projects. The way it works is, as I said, 0 margin top and bottom, but auto on the sides. If the margin is automatic, that means equal. The only way margins can be equal inside a parent would be for the object to be centered in the parent.

See why they call it a css trick?

Enter the flex

There is something that hates a hack. There is something inelegant and, let's face it, gross about using a side effect of setting margins to center a box. Perhaps that's why flexbox was invented--to avoid being gross.

Flexbox was my first CSS love. After hacking my way through margin: 0 auto and floats and clears and such, flexbox just made so much sense. It worked--more or less--like you'd think it would.

Most of the action in flexbox happens in the parent element. In this case, this is the parent div. I found this easy to miss when I was attempting to learn flexbox for the first time. So we set the parent div to display: flex and then use the property: justify-content: center.

            .parent-flex {
                border: 4px dotted black;
                height: 200px;
                display: flex;
                justify-content: center;
                 
            }
            .box {
                border: 4px solid black;
                height: 100px;
                width: 100px;
            }
        

The result is the same--a box centered within a div. However, besides the satisfaction of using a property in its intended way, we also have gained a whole new set of tools by invoking flexbox.

You have noticed that the box is centered horizontally, but not vertically. It's kind of nasty, how it clings there to the top of its div like a hanging bat, or maybe a trap that's getting set to crush our avatar as we innocently walk underneath it.

Flexbox makes this simple to fix with a single line.

            align-items: center;
        

That deserves a sound effect--a choir of angels giving an angelic sigh of enlightenment.

Now let's consider another situation. How to center an image in a div. This is a common need and also a source of great frustration to new folks.

            <div class="parent">
                <img src="./shepherd.png"/>
            </div>

        

What happens if we try our old tricks? Let's use the old magic spell, margin: 0 auto, and try to center Jupiter the German shepherd.

--Nope

We find that it has no effect. How infuriating is that?

How can this be? Something that works on a normal div shaped like a box doesn't work on an image? You see why we developers hat--er, no, that's a strong word. You see why we have such a complicated relationship to CSS.

But what if we try justify-content: center?

            .parent-flex-image {
                border: 4px dotted black;
                height: 200px;
                display: flex;
                justify-content: center;
            }
        

Ver Nice--

The lesson is: always use flexbox! It rocks!

But there's another lesson here, another trick, you might say. Part of you might be wondering--but why, why, why did my new margin: auto 0 trick not work on the image? And it's infuriating, I get it. So. The reason is, a div (which our square is) and an image (which our dog is), default to different display properties.

Divs default to display: block.

Images default to display: inline.

Discussing this at length is beyond the scope of this post, but suffice to say that block elements take up the whole page horizontally, whereas inline elements merely take up as much as they need to depending on their content. You can verify this by using a bit o' background color.

            .box-red {
                border: 4px solid black;
                height: 100px;
                background-color: red;
            }
            .parent {
                border: 4px dotted black;
                height: 200px;
            }
            .image1 {
                margin: 0 auto;
                outline: red;
            }
        

I have removed the width: 100px, put on a red background, and voila, the div we call box-red shows its true self. It expands the width of the page.


When I put an border around the image, which shows its true dimensions, you see it only takes up as much horizontal space as it must.

If you want to use the margin: 0 auto trick on the image, you must change its display to block.

            .image-border {
                display: block;
                border: 4px dotted red;
                margin: 0 auto;
            }
        

Good Job! Now never do that again


It's good to know the margin: 0 auto trick, but flexbox is so much better and, well, flexible. It makes everything easier, is more logical, and you don't have to play tricks like change the display type of the image or use side effects to accomplish simple tasks.

Plus, Jupiter says so.