All About 'margin: auto' in CSS: Centering and More
Tags: css, webdev, frontend
Published: 2023-11-03 07:15:16



_Margin_ is a very common property that is used in CSS all the time to control the spacing and layout of elements in a web page. Even in popular CSS frameworks like Bootstrap and Tailwind CSS, we have utility classes to specify margins for all or specific sides of an element. 


![different margin classes and properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fg11h9axcyas46viqioa.png)

Though we normally use lengths in units (such as rems, pixels, ems etc.) or percentages as values for margin property. _Do you know margin property also accepts a keyword called **"auto"** as value?_ 

Let's take a deeper look at what `auto` does and how it can be used!
<br/>
### :sparkles: What does `auto` mean? 
When an _**auto**_ keyword is used in margin property, the browser automatically calculates a _suitable margin_ for an element based on the space around it. `auto` essentially tells the browser to let the element _take up the available space_.
<br/>
### :sparkles: What does "taking up available space" mean? 
Suppose I have a `<div> tag` inside a `<section> tag` and it looks like the image below.


![a div element inside a section container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ti6kkx8mym24pxnm3k6v.png)

We know that block-level elements primarily take up the entire width of their parent so no space is left for `auto` to work on. Therefore, I've given the `<div> tag` a fixed width of 100px to create space inside its container.

:thought_balloon: **What do you think will happen if I assign margin-left: auto to this orange box?** 
The element moves all the way to the right side, using every bit of the _available space_ for its left margin.

![orange box moves all the way to the right side](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpbh9x7p1ouo2djcpo55.png)

`auto` takes up all the available space for the margin it is applied for. But there are few points that should be kept in mind when using `auto`

- For block-level elements, it works only with margin-left and margin-right properties.
- It shows no effect for _floated_ and _inline elements_. 
- It works for absolute elements only under _certain_ conditions.
- It works for margin-top and margin-bottom properties only with flexbox or grid.


### :sparkles: Using `auto` with block-level elements
When using with block-level elements, `auto` only works on _margin-left_ and _margin-right_ properties given that the element has a fixed width, leaving space in its parent container. We saw earlier how `margin-left : auto` pushed the element to the _right edge_ of its container.

:thought_balloon: **What do you think will happen if I also add margin-right: auto to that orange box?**
`auto` will divide all the available space _**equally**_ between right and left margins and hence _center align_ the element _horizontally_ within the parent container.


![div is center aligned horizontally](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qb76c9980yokju8bk0s.png)

This is the most popular use case of `auto`. With just _**one line**_ we can _horizontally_ center images, divs and other block-level elements within their parent containers. 

You can use either `margin` shorthand property or `margin-inline` to center align the element horizontally. 
:warning: _Do remember that it will work only for block-level elements with fixed widths!_

```css
   element {
     /* use any one of the below properties */
      margin: 0 auto; 
       /* or */
      margin-inline: auto;
  }
```  

### :sparkles: Using `auto` with absolute elements
Absolutely positioned elements are out of the normal flow of a document so it feels right that `margin: auto` should not work for it. But there seems to be an _exception_ which allows us to use `auto` to center align an absolute element within its parent both _vertically_ and _horizontally_.

:paperclip: **[W3C Spec](https://www.w3.org/TR/css-position-3/#abs-non-replaced-width) specifies** ⟶

> If all three of _"left"_, _"width"_, and _"right"_ are `auto`: First set any auto values for "_margin-left_" and "_margin-right_" to 0. 

> If none of the three is `auto`: If both "_margin-left_" and "_margin-right_" are auto, solve the equation under the extra constraint that the two margins get equal values

W3C Spec specifies the same for "_height_", "_top_" and "_bottom_" properties. This means that we can _center_ align an absolute element ⟶
- _horizontally_ if its _left_ and _right_ properties have same values and has a fixed _width_
- _vertically_ if _top_ and _bottom_ have same values and has a fixed _height_

By using these exceptions we can assign below properties to center align an absolute element within its parent.

```css

   .parent {
      position: relative;
      height: 150px; 
    }

   .child {
      position: absolute;
      margin: auto;
      inset: 0; /* sets left, right, top & bottom to 0 */
      width: 70px;
      height: 20px;
    }

```
`inset: 0` is shorthand for setting all four properties — _left_, _right_, _top_ and _bottom_ as 0. 


![auto can be used to center align an absolute element under certain conditions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/enr86s4tijt9zdyptffg.png) 

Though this method works to _center align_ an absolute element within a parent because of the _exceptions_ in W3C Spec. It is best to use a combination `left`, `top` and transform `translate` properties to achieve this.

```css

    .parent {
        position: relative;
     }

    /* use this method to center align an absolute element */
    .child {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
     }

```

### :sparkles: Using `auto` with flexbox or grid
Flexbox and grid both allows us to use `auto` with margin property to center align an element both _horizontally_ and _vertically_.

Let's take our previous example of a `<section> tag` with a `<div> tag` inside it and this time set `display: flex` property on the `<section> tag`.

```css

    section {
       height: 120px; /* height is required to align vertically */
       display: flex;
     }

    div {
      width: 80px;
      margin: auto;
    }

```
`auto` works on all _4 margin properties_ and places the orange box in the _middle_ of its flexbox parent. 
:warning: Do remember to add _height_ to flexbox container if you want to use `auto` on `margin-top` and `margin-bottom` properties on its children, otherwise they won't work.


![flexbox allows us to use auto on all margin properties](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o0n8kw8ja0a5lfpactkb.png)


If you replace `display: flex` with `display: grid` for `<section> tag`, you will get the same result.

### :sparkles: Creating Navbars with `auto` and CSS flexbox
One of the most interesting use case of `auto` that I came across recently was making navigation bars with the help of CSS flexbox!

I have prepared a very basic navigation bar with a title, few links and a sign up and login buttons. Flexbox is used to align all these elements in a row.

![A navigation bar to demo the use of auto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e0xq54q7xw5sjuxvrmmw.png)

:thought_balloon: **What if I want all the links and the 2 buttons on the right side of navbar?**
One of the ways is to use `justify-content: space-between` on flexbox container since we have title in one tag and all the links and buttons inside a `<ul> tag`.

Another way is to add `flex-grow: 1` on `<ul> tag` and use `margin-left: auto` on the first `<li> tag` that is link _Products_

```css

   ul {
     flex-grow: 1
   }
    
   /* <li> tag with link 'Products' */
   /* nth-child(1) selects first <li> tag */
   li:nth-child(1) {
     margin-left: auto;
   }

```

By default, flex items take up _minimum space_ required to fit their content. So to create space for `auto` to take we added flex-grow: 1 on `<ul> tag` so that it grows to fill the remaining space in its flexbox parent.


![all links and buttons moved to right side](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cybww4ovdi61sde0avzm.png)

:thought_balloon: **What do you think will happen if I set `margin-left: auto` on sign-up button also?**
All the links are now in the middle and the 2 buttons are at the end. We got another version of navbar very easily with just one line of code!


![links are in the middle and buttons are at the end](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzxvfa9ulm6rf4sa2bg1.png)

In the same way, we can make sidebars where say socials icons are at the end, title at the top and all the links in the middle. We just have to give flex container a _fixed height_ and use `margin-top: auto` on the first link and the social icon element. 

### :sparkles: Conclusion
Throughout this article, we looked at how `auto` keyword can be used with `margin` property. We also learnt how it can be used with flexbox to easily make beautiful versions of navigation bars.

That's all for this article. Thank you for reading!! 😊

I hope you found this article helpful! Feel free to comment down your feedbacks!! I would love to read them and improve. You can also buy me a [coffee](https://www.buymeacoffee.com/ritikaagrawal08). For more content around CSS, follow me on [Twitter](https://twitter.com/RitikaAgrawal08).