Top & Left vs margin-top & margin-left - html

What is the difference between using top and left properties and top and left margins?
I know top and left are usually used in position:absolute situation but I'm still wondering if there is any major difference.
ex:
position:absolute;
top:5px;
left:5px;
-vs-
margin-top:5px;
margin-left:5px;

Well, the main difference is that absolutely positioned elements are pulled out of the content flow.
But also with relatively positioned elements, the surrounding content may become obfuscated.
Margins on the other hand are added to the element's size while the surrounding content flows accordingly.
See this sample fiddle with some differences.
Surely there are situations where both deliver the same results, but under normal conditions, these two aproaches aren't simply exchangeable nor comparable.

A There's a semantic difference. Box offsets like top specify how far a box's margin edge (dotted edges in the image below) is offset from a reference edge (For absolutely positioned elements, that's the top edge of the box's containing block). Margin properties like margin-top specify the width of the margin area of a box (The distance TM between the dotted edge and and solid edge in the image below).
B top and left apply only to positioned elements (elements with position set to anything other than static) while margin-top and margin-left apply to all elements except elements with table display types other than table-caption, table and inline-table.

Margin describes the space between your box and adjacent boxes. Boxes that are positioned relatively (i.e. that are part of the normal flow) will keep the sufficient space between them that each one's "margin" requirements are met (called "margin collapsing").
top and left on the other hand are positional attributes that specify where your box is located; for absolutely positioned boxes the values are taken relative to the nearest containing box which is itself absolutely positioned. The top/left/bottom/right attributes specify the location of the respective edge of your box including its margin.
In short, the two are entirely different concepts. For normally flowed boxes you should use margin to control the spacing between neighbouring boxes.

Related

Why does clearfix hack only work on floated elements? [duplicate]

This question already has answers here:
Why can you clear floating elements but not absolutely positioned elements?
(2 answers)
Closed 6 years ago.
Both floated and absolutely positioned elements are taken out of the document flow. Then why does clearfix hack only work on floating elements not upon absolutely positioned elements?
There is a common misconception that floats are removed permanently from the document flow.
This is not the case, floated element are removed from their standard position in the flow and shifted as far as possible to the left or to the right on their current line, depending on the specified floating direction.
W3 Spec
A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box.
A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float. If there is a line box, the outer top of the floated box is aligned with the top of the current line box.
Floated elements affect the elements around them, absolutely positioned elements do not.
W3 Spec on Absolute Positioning
In the absolute positioning model, a box is explicitly offset with respect to its containing block. It is removed from the normal flow entirely (it has no impact on later siblings).
Notice the difference?
So a clearfix (or clearance) only affects floated elements. A clearfix is not used to clear floating elements, it's used to contain floating elements inside another element.
There's a great article on CSS-Tricks which explains All About Floats and covers the differences between them and positioning.
FLOAT :
When you float an element, The element is not taken out.
Float does not removes an element from the document’s flow.
Position ABSOLUTE :
When you position an element the element is take out (Placed above other elements).
Absolute positioning removes an element from the document’s flow. The element given absolute positioning will no longer affect the layout of other elements in the document.
This is the best example you can understand easily : Check this

Why does margin-top affect the placement of an absolute div?

I have two divs in this jsFiddle - http://jsfiddle.net/z4062jfn/ - with absolute positioning. I didn't expect any margin values given to the divs to affect their absolute position. And this is true for a margin-bottom value given to the top div (uncomment line 8 of CSS). But a margin-top value given to the bottom box (uncomment line 19 of CSS) does move the bottom div position down by that amount.
What is there in this situation that lets a margin rule override an absolute position rule - sometimes?
<div id="box1"><p>box 1</p></div>
<div id="box2"><p>box 2</p></div>
The simple factual explanation for why this happens is that the offset properties top, right, bottom and left actually respect the corresponding margin properties on each side. The spec says that these properties specify how far the margin edge of a box is offset from that particular side. The margin edge is defined in section 8.1.
So, when you set a top offset, the top margin is taken into account, and when you set a left offset, the left margin is taken into account.
If you had set the bottom offset instead of the top, you'll see that the bottom margin takes effect. If you then try to set a top margin, the top margin will no longer have any effect.
If you set both the top and bottom offsets, and both top and bottom margins, and a height, then the values become over-constrained and the bottom offset has no effect (and in turn neither does the bottom margin).
If you're looking to understand why the spec defines offsets this way, rather than why browsers behave this way, then it's primarily opinion-based, because all you'll get is conjecture. That said, Fabio's explanation is quite reasonable.
Because an absolutely positioned box is removed from the normal flow and is assigned a position with respect to the containing block. If you don't define a containing block, then it's body.
So, with that in mind, think of the containing block as a coordinates axis that starts at top left. If you give your element this properties:
position: absolute;
top:100px;
left:100px;
just like you did, you will have leave an empty space above and left, thus, if you apply margin-top or margin-left, it will work, because your elements are capable to virtually go through every pixel of both axises up to that 100px top and 100px left position, and same applies for negative margins. However, since position:absolute removes the element from the flow and any impact on any subsequent sibling element, it's easy to see that nothing can happen after the element "finishes", hence margin-bottom and margin-right won't work since they don't have anything to get margin from.
I have made an image to show the behavior since my explanation might be a bit obscure
Your margin bottom is not working since you put the top property in your divs. Remove top and your margin bottom will work for your #box1.
Margin-bottom affect too. See the code below, if you set a bottom reference in #box1 it will apply 20px in margin-bottom.
http://jsfiddle.net/t5ooot7u/
#box1 {
width:200px;
height: 100px;
background-color:gold;
position: absolute;
bottom:230px;
left:100px;
margin-bottom:20px;
}

How height: auto works in HTML and CSS?

In CSS and HTML how does height: auto work? What do browsers consider while calculating height of the element, for which height is set to auto?
You can split two cases:
div and other containers: the height is the one the browser will use if you don't specify anything, trying to contain the element contents. (read Mathijs's answer for more details)
images and other block elements with intrinsic dimensions (width and height): if you specify the width, then "height: auto" will scale proportionally.
So, in other words, is useless unless you need to reset the browser behaviour or keep proportions to some objects.
Here's an excerpt on this copied from the W3C CSS2 spec
If it only has inline-level children, the height is the distance
between the top of the topmost line box and the bottom of the
bottommost line box.
If it has block-level children, the height is the distance between the
top margin-edge of the topmost block-level child box and the bottom
margin-edge of the bottommost block-level child box.
Absolutely positioned children are ignored, and relatively positioned
boxes are considered without their offset. Note that the child box may
be an anonymous block box.
In addition, if the element has any floating descendants whose bottom
margin edge is below the element's bottom content edge, then the
height is increased to include those edges. Only floats that
participate in this block formatting context are taken into account,
e.g., floats inside absolutely positioned descendants or other floats
are not.

the concept of negative margins - have i understood?

i read that negative margin-top and left takes the element and pushes it in this direction. On the other hand negative bottom and right margins draw the rest of the content over the element.
Question
I have a floated element float:right; wrapped in the body tag. Negative left margin will move it to the left.
Negative RIGHT margin wont do anything at all because the document ends where this negative margin starts and there is nothing to draw over the element (or pull over it)?
Am i correct?
Negative margins will always work on block boxes the same way that positive margins do. They just move a box and/or surrounding boxes in the opposite direction that positive margins do. Heck, negative margins can even collapse.
If any overflow occurs, then related boxes will adjust and accommodate for this box's movement.
If an element is floated in a certain direction, then a margin on the side that it's being floated towards will have an effect on its own position, and a margin on the opposite site will influence it relatively to any succeeding floats.
Negative RIGHT margin wont do anything at all because the document ends where this negative margin starts and there is nothing to draw over the element (or pull over it)?
No. There is this thing called the canvas, which has a theoretically unlimited amount of space for expansion. Got a margin pushing an element out of the page body or page root? NBD, just expand the canvas in that direction, make a scrollbar in the viewport which is used to display this canvas, and done.
It's the same as if you had a negative margin on an element whose parent has overflow: auto, because the root element itself has overflow: auto by default (since you can't really have stuff visibly overflowing the browser window itself...).
jsFiddle proof-of-concept
Many people believe the same misconception about negative margins. The behavior you describe tends to match many negative margins cases, but it is explaining them from a flawed perspective. Actually, negative margins have the same effect on any side of the box, but not in terms of "move the box" or "draw other content in".
For example, a left-margin: -20px means "position the element as if its left edge were 20 pixels inwards from its true left edge". A right-margin: -20px means exactly the same thing, but for the right edge.
In the simplistic description you have provided, the negative left margin would indeed shift the element itself leftwards, because its left edge is placed adjacent to the previous element's right edge, but the browser pretends that our element's left edge is actually moved rightwards, so the content of the element itself appears moved leftwards.
With the negative right margin, the browser places the next element's left edge adjacent to our element's right edge, but it pretends that our element's right edge is moved leftwards, so the next element itself appears moved leftwards.
In both cases, the only thing that is changed is the browser's notion of the position of the element's edges.
When you have a right-floated element, the browser will position it so that its right edge will be adjacent to the left edge of the previous right-floated element, or if there is no previous right-floated element, it will be adjacent to the right edge of its position parent (which is the closest parent element with a position style that is not static). In your case you don't have a previous right-floated element, so the browser positions your element so that its right edge is adjacent to the parent's right edge, but it pretends your element's right edge is moved leftwards, so your actual content is moved rightwards, protruding outside of the parent element.
Here is a demonstration. The box with the blue border has negative left and right margins. The yellow box inside it represents how the browser considers it — it is narrower than the blue-bordered box, because the negative margins tell the browser to move its edges inwards, eating from the element's actual size. As you can see, its positioning box is placed exactly as any element would be, touching its left and right siblings on both sides. And the actual content extends in both directions by exactly the same amount, because its negative margins are the same. The perceived change is that the element itself is moved left due to its left margin, and following content is moved left due to its right margin, but as you can see, in reality, the effect is exactly the same on both sides.
Negative right margin sure works! http://fiddle.jshell.net/H6mjC/
also made a fiddle. Of course negative margin is working.
fiddle with negative margin
enter code here

Why this behaviour (on ALL browsers) with margin-top?

This is my code :
HTML
<div class='father'>
<div class='son'>Son</div>
</div>
CSS
.father
{
background-color:blue;
}
.son
{
margin-top:50px;
background-color:red;
height:50px;
}
Where is the background-color blue of the father?
I know how to fix this problem (putting padding-top:1px to the father) but I'd like to know why of this behaviour!
For me it doesnt make sense, because on every browsers, not only IE, this is the behaviour.
This is a result of Collapsing Margins. You can read a good article by Eric Meyer on this topic where he illustrates this exact behavior. The following image is from his article.
Here's what the CSS2 specification has to say about it.
8.3.1 Collapsing margins
If the top and bottom margins of a box are adjoining, then it is
possible for margins to collapse through it. In this case, the
position of the element depends on its relationship with the other
elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as
the parent's.
Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved.
The position of the element's top border edge is the same as it
would have been if the element had a non-zero bottom border.
Note that the positions of elements that have been collapsed through
have no effect on the positions of the other elements with whose
margins they are being collapsed; the top border edge position is only
required for laying out descendants of these elements.
Source: http://www.w3.org/TR/CSS2/box.html#collapsing-margins
This is because the div is a block-level element. Certain block-level elements don't contain any padding by default. Divs are one such element. Block-level elements will take up the entire height and width of the container while respecting any padding it may contain.
W3C Visual formatting model
The parent element's height is set to its content's height by default. Once you set a height on the parent, that's no longer the default. Checking up on it, I believe that the padding adds to the height. So, the height is originally determined by the content unless otherwise stated in the CSS. Then, in most cases (IE 6 may be the exception), the padding is added to the height.
Good thing about SO, it helps us be much more detailed in our responses. :)
In CSS, block level elements naturally fills the elements content area, so your "son" div is filling your "father" div completely. Of course, you can bypass this by adding margin/padding/height to your parent div.
You're setting blue explicitly:
.father {
background-color:blue;
}
It's overridden (thanks to the "C" in CSS a.k.a cascading) but the style remains on your parent element (here, appropriately named "father").
If your .father box receives any height at all (check in the Firebug/Chrome dev tools inspector) than the blue is going to show through. I am guessing this is what you're seeing in IE (that or perhaps there's a flash of content before your child element style comes in). I don't think the IE debug tools show bounding boxes but you can test the element for it's height using JavaScript.
Moving outwards from the content, you have padding, border, and margin (as you probably know). Background covers only padding, but not margin.