Magnus
Magnus

Reputation: 7821

Negative Margin Adds Unwanted 1px Extra Spacing

Consider the following HTML and CSS

.outer {
  border: 1px solid red;
  margin-left: -10px;
}

.inner {
  border: 1px solid black;
  width: 50px;
  margin-left: 10px;
}
body {
  border: 1px solid blue;
}
<div class="outer">
  <div class="inner">
    inner
  </div>
</div>

Where is that 1px extra spacing on the left, between the inner and outer div, coming from?

Change the negative margin to -11px, and it works as it should (no gaps).

You can also remove all the margins and compare with the "negative + positive" scenario above, to see how the two are not the same.

Thank you.


EDIT

After figuring it out, I just wanted to share the below in case helpful to future visitors.

  1. The inner div is back to the exact spot it was when it started, after applying the -/+10px. It is just that the border that used to be in between the content edge of the body element, and the margin edge of the inner div (i.e. outer div's border) has shifted 10px to the left together with outer div. Thus, it works as it should without any oddities.
  2. Margins of a child box naturally apply from the content edge of its parent box. That is how the box model should work. It is not possible to change that behavior with box-sizing: border-box
  3. Possible solutions to the eliminate gap include (but are not limited to):
    • Converting the CSS to SCSS, storing the border width in a variable and subtracting that variable from parent's margin. (It was not necessary to convert to SCSS and use a variable, but it make the style sheet much easier to maintain and update.)
    • Eliminating the need for a negative margin altogether with JavaScript
    • Using outline instead of border on the parent div

Upvotes: 1

Views: 676

Answers (4)

Sysix
Sysix

Reputation: 1796

Instead of using border fothe outer element. You can use outline for it.

.outer {
  outline: 1px solid red;
}

.inner {
  border: 1px solid black;
  width: 50px;
  margin-left: 10px;
}

body {
  border: 1px solid blue;
}
<div class="outer">
  <div class="inner">
    inner
  </div>
</div>

Upvotes: 0

StefanDimi
StefanDimi

Reputation: 174

Sorry for wrong answer, i was writing in a rush... the math:

(-10pxMargin + 10pxMargin + 1pxBorder) = 1

you need

(-11pxMargin + 10pxMargin + 1pxBorder) = 0

let me know if this is clear enough, the thing is that margin doesnt include borders.

Upvotes: 2

Jos van Weesel
Jos van Weesel

Reputation: 2188

I think it has to do with the .outer border. You can see below that when the red border is moved 10px to the left, there is a gap where it would have been if it wasn't moved to the left (when the margin is 0).

And because the .inner div is relative to the .outer div, it doesn't 'fill up' that 1px gap it creates by moving .outer 10 pixels to the left.

Here you can see the gap. (It looks like 2 pixels because the page is zoomed in by 200%)


Edit with extra info:

Extra "proof" to show that the extra space comes from the .outer div, if you remove the 1px width of the .outer border, you also remove the gap:

Upvotes: 3

Gerardo BLANCO
Gerardo BLANCO

Reputation: 5648

That extra pixel is from the .outer element.

.outer {

  margin-left: -10px;
}

.inner {
  border: 1px solid black;
  width: 50px;
  margin-left: 10px;
}
body {
  border: 1px solid blue;
}
<div class="outer">
  <div class="inner">
    inner
  </div>
</div>

Upvotes: 1

Related Questions