A common trick for vertical positioning elements is to use the following CSS:
.item {
position:absolute;
top:50%;
margin-top:-8px; /* half of height */
height: 16px;
}
When seen in the metric view as in Chrome this is what you see:
However, there is no visual margin depicted when you hover over the element i.e. the margin is 'outside' the border and can be visualized. But negative margins don't show up. How do they look and what is it that makes it different?
Why is margin-top:-8px
not the same as margin-bottom:8px
?
So just how do negative margins work and what's the intuition behind them. How do they 'bump up' (in case of margin-top < 0
) an item?
Just to phrase things differently from the great answers above, as that has helped me get an intuitive understanding of negative margins:
A negative margin on an element allows it to eat up the space of its parent container.
Adding a (positive) margin on the bottom doesn't allow the element to do that - it only pushes back whatever element is below.
I'll try to explain it visually:
/**_x000D_
* explaining margins_x000D_
*/_x000D_
_x000D_
body {_x000D_
padding: 3em 15%_x000D_
}_x000D_
_x000D_
.parent {_x000D_
width: 50%;_x000D_
width: 400px;_x000D_
height: 400px;_x000D_
position: relative;_x000D_
background: lemonchiffon;_x000D_
}_x000D_
_x000D_
.parent:before,_x000D_
.parent:after {_x000D_
position: absolute;_x000D_
content: "";_x000D_
}_x000D_
_x000D_
.parent:before {_x000D_
top: 0;_x000D_
bottom: 0;_x000D_
left: 50%;_x000D_
border-left: dashed 1px #ccc;_x000D_
}_x000D_
_x000D_
.parent:after {_x000D_
left: 0;_x000D_
right: 0;_x000D_
top: 50%;_x000D_
border-top: dashed 1px #ccc;_x000D_
}_x000D_
_x000D_
.child {_x000D_
width: 200px;_x000D_
height: 200px;_x000D_
background: rgba(200, 198, 133, .5);_x000D_
}_x000D_
_x000D_
ul {_x000D_
padding: 5% 20px;_x000D_
}_x000D_
_x000D_
.set1 .child {_x000D_
margin: 0;_x000D_
position: relative;_x000D_
}_x000D_
_x000D_
.set2 .child {_x000D_
margin-left: 75px;_x000D_
position: relative;_x000D_
}_x000D_
_x000D_
.set3 .child {_x000D_
margin-left: -75px;_x000D_
position: relative;_x000D_
}_x000D_
_x000D_
_x000D_
/* position absolute */_x000D_
_x000D_
.set4 .child {_x000D_
top: 50%;_x000D_
left: 50%;_x000D_
margin: 0;_x000D_
position: absolute;_x000D_
}_x000D_
_x000D_
.set5 .child {_x000D_
top: 50%;_x000D_
left: 50%;_x000D_
margin-left: 75px;_x000D_
position: absolute;_x000D_
}_x000D_
_x000D_
.set6 .child {_x000D_
top: 50%; /* level from which margin-top starts _x000D_
- downwards, in the case of a positive margin_x000D_
- upwards, in the case of a negative margin _x000D_
*/_x000D_
left: 50%; /* level from which margin-left starts _x000D_
- towards right, in the case of a positive margin_x000D_
- towards left, in the case of a negative margin _x000D_
*/_x000D_
margin: -75px;_x000D_
position: absolute;_x000D_
}
_x000D_
<!-- content to be placed inside <body>…</body> -->_x000D_
<h2><code>position: relative;</code></h2>_x000D_
<h3>Set 1</h3>_x000D_
<div class="parent set 1">_x000D_
<div class="child">_x000D_
<pre>_x000D_
.set1 .child {_x000D_
margin: 0;_x000D_
position: relative;_x000D_
}_x000D_
</pre>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
<h3>Set 2</h3>_x000D_
<div class="parent set2">_x000D_
<div class="child">_x000D_
<pre>_x000D_
.set2 .child {_x000D_
margin-left: 75px;_x000D_
position: relative;_x000D_
}_x000D_
</pre>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
<h3>Set 3</h3>_x000D_
<div class="parent set3">_x000D_
<div class="child">_x000D_
<pre>_x000D_
.set3 .child {_x000D_
margin-left: -75px;_x000D_
position: relative;_x000D_
}_x000D_
</pre>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
<h2><code>position: absolute;</code></h2>_x000D_
_x000D_
<h3>Set 4</h3>_x000D_
<div class="parent set4">_x000D_
<div class="child">_x000D_
<pre>_x000D_
.set4 .child {_x000D_
top: 50%;_x000D_
left: 50%;_x000D_
margin: 0;_x000D_
position: absolute;_x000D_
}_x000D_
</pre>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
<h3>Set 5</h3>_x000D_
<div class="parent set5">_x000D_
<div class="child">_x000D_
<pre>_x000D_
.set5 .child {_x000D_
top: 50%;_x000D_
left: 50%;_x000D_
margin-left: 75px;_x000D_
position: absolute;_x000D_
}_x000D_
</pre>_x000D_
</div>_x000D_
</div>_x000D_
_x000D_
<h3>Set 6</h3>_x000D_
<div class="parent set6">_x000D_
<div class="child">_x000D_
<pre>_x000D_
.set6 .child {_x000D_
top: 50%;_x000D_
left: 50%;_x000D_
margin: -75px;_x000D_
position: absolute;_x000D_
}_x000D_
</pre>_x000D_
</div>_x000D_
</div>
_x000D_
I wonder if this question has been answered well: how css margins work and why is it that margin-top:-5; is not the same as margin-bottom:5;?
Margin is distance from the surroundings of the element. margin-top says "... distance from surroundings as we measure from top 'side' of the element's 'box' and margin-bottom being the distance from the bottom 'side' of the 'box'". Then margin-top:5; is concerned with the top 'side' perimeter,-5 in that case; anything approaching from top 'side' can overlap top 'side' of element by 5, and margin-bottom:5; means distance between element bottom 'side' and surrounding is 5.
Basically that but affected by float'ed elements and the like: http://www.w3.org/TR/CSS2/box.html#margin-properties.
http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/
I stand to be corrected.
Because you have used absolute positioning, and specified a top percentage, only margin-top will affect the location of your .item object. If instead you positioned it using bottom: 50%, then you'd need margin-bottom -8px to centre it, and margin-top would have no effect.
Margin affects the boundaries of an element in terms of positioning it, either absolutely as in your case, or relative to neighbouring elements. Imagine that margin is the foundations of your element on which it sits. They are typically the same size as it, but can be made larger or smaller on any or all of the four edges.
Your CSS tells the browser to position the top of your element the margin at a point 50% of the way down the page. However, as all elements are not a single pixel, the browser needs to know which part of it to line up 50% of the way down the page. For lining up the top of the element, it uses the top margin. By default this is in line with the top of the element, but you can alter it with CSS.
In your case, top 50% would result in the top of the element starting in the middle of the page. By applying a negative top margin, the browser uses the point 8px into the element from the top (ie the line across the middle of it) as the place to position at 50%.
If you apply a positive margin to the bottom, this extends the line the browser uses to position the bottom out away from the element itself, giving a gap between it and any adjacent element below, or affecting where it is placed absolutely if positioning based on the bottom.
good points already made here, but while there is lots of information about how rendering of margins is accomplished by the browser, the why isn't quite answered yet:
"Why is margin-top:-8px not the same as margin-bottom:8px?"
what we also could ask is:
Why doesn't a positive bottom margin 'bump up' preceding elements, whereas a positive top-margin 'bumps down' following elements?
so what we see is that there is a difference in the rendering of margins depending on the side they are applied to - top (and left) margins are different from bottom (and right) ones.
things are becoming clearer when having a (simplified) look at how styles are applied by the browser: elements are rendered top-down in the viewport, starting in the top left corner (let's stick with the vertical rendering for now, keeping in mind that the horizontal one is treated the same).
consider the following html:
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
analogous to their position in code, these three boxes appear stacked 'top-down' in the browser (keeping things simple, we won't consider here the order
property of the css3 'flex-box' module). so, whenever styles are applied to box 3, preceding element's positions (for box 1 and 2) have already been determined, and shouldn't be altered any more for the sake of rendering speed.
now, imagine a top margin of -10px for box 3. instead of shifting up all preceding elements to gather some space, the browser will just push box 3 up, so it's rendered on top of (or underneath, depending on the z-index) any preceding elements. even if performance wasn't an issue, moving all elements up could mean shifting them out of the viewport, thus the current scrolling position would have to be altered to have everything visible again.
same applies to a bottom margin for box 3, both negative and positive: instead of influencing already evaluated elements, only a new 'starting point' for upcoming elements is determined. thus setting a positive bottom margin will push the following elements down; a negative one will push them up.
A margin-top of -8px means it will be 8px higher than if it had 0 margin.
A margin-bottom of 8px means that the thing below it will be 8px further down that if it had 0 margin.
Margin is the spacing outside your element, just as padding is the spacing inside your element.
Setting the bottom margin indicates what distance you want below the current block. Setting a negative top margin indicates that you want negative spacing above your block. Negative spacing may in itself be a confusing concept, but just the way positive top margin pushes content down, a negative top margin pulls content up.
Source: Stackoverflow.com