CSS Puzzle: how does margin auto + left + right calculation works?

46 views Asked by At

I played with this layout: 1 responsive div with two equal sections and a purple fixed size div, that should be placed responsive in the middle of the left section (no matter how one resizes the browser window the div.abs stays in the center of the left section)

One possible solution is shown below (or here)

The solution

left: calc(25% - 20px);

is straightforward - take the middle of the first section (50% - 25% = 25% and subtract the half of the div.abs).

But if we substitute it with

margin: auto;
left: -50%;
right: 0px; 

it is still working!

Could someone explain how the calculation is done in that case?

.container {
  display: flex;
  position: relative;
  border: 1px solid Tomato;
  margin: 20px;
  height: 50vh;
}

.abs {
  position: absolute;
  background-color: MediumPurple;
  width: 40px;
  height: 40px;
/*   margin: auto;
  left: -50%;
  right: 0px; */
  left: calc(25% - 20px);
  top: calc(50% - 20px);
}

.left {
  background-color: DarkSeaGreen;
  width: 50%;
}

.right {
  background-color: PapayaWhip;
  width: 50%;
}
<div class="container">
  <div class="abs"></div>
  <div class="left"></div>
  <div class="right"></div>
</div>

1

There are 1 answers

1
Temani Afif On

You need to refer to the Specification and the below formula:

'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = width of containing block

We have no border and padding so we can simplify to:

'left' + 'margin-left' + 'width' + 'margin-right' + 'right' = width of containing block

Then the following will apply for your case:

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,

So let's solve the equation:

left + 2*m + width + right = 100%
-50% + 2*m + 40px + 0 = 100%
2*m = 150% - 40px
m = 75% - 20px

Now if you define the margin equal to the above and with that you define either left or right you get the same result:

.container {
  display: flex;
  position: relative;
  border: 1px solid Tomato;
  margin: 20px;
  height: 50vh;
}

.abs {
  position: absolute;
  background-color: MediumPurple;
  width: 40px;
  height: 40px;
  top: calc(50% - 20px);
  right: 0px; /* or left: -50% */
  margin: 0 calc(75% - 20px);
}

.left {
  background-color: DarkSeaGreen;
  width: 50%;
}

.right {
  background-color: PapayaWhip;
  width: 50%;
}
<div class="container">
  <div class="abs"></div>
  <div class="left"></div>
  <div class="right"></div>
</div>

Basically your element is centered between the point "left: -50%" and "right:0". So when you define margin: auto, you center the element between the position you define with left and right. That's why centering an element requires left and right to be equal.

Related question: Why magin:auto is not enough to center position absolute or fixed?