Take the 2-minute tour ×
<div style = "float : left; background-color: #dd3fb8;">
    <a style = "margin-left : 10%;">a</a> 

In the example above, the letter "c" would be on new line, but if I set "margin-left" to px unit, "c" would be on the same line as "a" and "b". Why does this happen?

share|improve this question
It depends on the difference between how many pixels are being calculated for the 10% and the number of pixels you are using for those units –  tlindell Jun 9 at 2:40
@tlindell: Doesn't seem like it. If you specify an absurd pixel value like 500px, it still behaves the same as 10px even though it's obviously far greater than a 10% margin. –  BoltClock Jun 9 at 2:48

3 Answers 3

up vote 13 down vote accepted

Unfortunately, the CSS2.1 spec doesn't appear to have a clear answer to this. In fact, I would say this is well within the realm of undefined behavior.

Here are the relevant points I can find:

  • Floats without a specified width will shrink to fit their contents. In the case of floats with only inline content, the float needs to be made just wide enough to fit its contents on a single line (notwithstanding explicit line breaks) and no more.

  • Percentage margins are calculated based on the width of the containing block.

    Note that it says:

    If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.

    ... but as far as I can see, the behavior is consistent across all browsers.

    That being said, the reason this statement applies is because since the margin of the inline element falls within the content bounds of the float, it can be said that the width of the float (the containing block of the inline elements) depends on the this element (the element having the margin).

Here's what I can deduce based on the points above:

  • When the margin is specified as a percentage, the width of the float is calculated without taking the margin into account, because it's not possible to calculate the margin until the width of the float has been determined.

    The margin is then calculated based on the used width of the float, and the letter "c" wraps to a new line as a result of being pushed forward by the margin on "a". The width of the float does not change.

    Again, none of this behavior is specified at all, and so technically it's not in violation of the spec. However, it seems sensible.

  • When the margin is specified as a pixel value, the margin is calculated first. The width of the float is then calculated taking this margin into account (remember that horizontal margins do apply to inline elements as normal). Per the shrink-to-fit algorithm, this is the preferred width: just wide enough to contain all the inline elements on a single line.

    Unlike with percentage margins, this is very clear-cut, as implementations should have no trouble calculating computing absolute values for margins first.

I would be hard-pressed to call this a bug in any of the browsers, especially since they all behave consistently.

Lastly, of course, you can avoid this undefined behavior entirely simply by giving your floats explicit widths where possible. It does help to understand why you should do so, however.

share|improve this answer
+1 That makes a lot of sense. I'm going to delete my answer. –  JW Lim Jun 9 at 3:19
Why my answer had nothing to do with the question in hand? A floated element should have an explicitly set width (unless it is a replaced element, like an image). This ensures that the float behaves as expected and helps to avoid issues in certain browsers. If the size of the floated box exceeds the available horizontal space, the floated box will be shifted down. –  Dipaks Jun 9 at 3:19
@Dipaks: You answer is basically saying, “give your floated element a fixed width to avoid this problem”, but it doesn’t explain the problem resp. its cause itself. –  CBroe Jun 9 at 3:25
@Dipaks: True, I couldn't have known beforehand that it was related somehow (re: not giving floats a width). But your answer didn't make any attempt to explain why it could have been related, and honestly it seemed like you were avoiding the question entirely. It's not a useful answer, especially not to the OP who is asking why. So while I could indeed have been more specific with my reasoning (and for that I apologize), I believe my downvote still stands. –  BoltClock Jun 9 at 3:27
“If the size of the floated box exceeds the available horizontal space, the floated box will be shifted down” – that was actually besides the point, because it is not the floated box that gets shifted down here, but only one of its inline descendants. And the link you supplied with that line does not go into the specific problem that was in question here either, but is just a general explanation of float. –  CBroe Jun 9 at 3:31

Since your div is floated, and its width is auto (implicitly), http://www.w3.org/TR/CSS21/visudet.html#float-width applies:

If 'width' is computed as 'auto', the used value is the "shrink-to-fit" width.

“shrink-to-fit” width basically means, let the element be as wide as its content requires it to be.

Now without the margin-left, that is no problem: All three of your a elements are inline elements that contain a specific character each – easy enough to determine their individual widths, and add them up.

But now you want a margin-left in percent, and here things get complicated – if we look at the definition for margin-left, it says:

Percentages: refer to width of containing block

Now, that leaves us in a bit of a pickle, since the width of the containing block (which is established by the floated div element), is computed based on its content – but now this margin-left would change the overall width of that content, but is in itself dependent on the width of the containing block, which it itself influences …

That’s a classical problem of two measurements that are dependent on each other … and that is therefor basically unsolveable.

http://www.w3.org/TR/CSS21/box.html#margin-properties says,

 The percentage is calculated with respect to the width of the generated box's containing block. […]

Edit: Basically the same as what BoltClock said in his answer, just took me a little longer …

share|improve this answer

The link has a left margin of 10%, 10% of how much? The parent element is floated left which means it does not have a width of its own, instead it expands as much as its contents. If you try to imitate how the browser would compute the resulting box and you will find yourself in a fix:

  • Let the width of the content (and therefore the container) be 30px
  • Add 10% of 30px = 3px left margin to the link
  • The resulting width of the container is 30 + 3 = 33px

This creates a loop where margin increases as outer width is increased and outer width increases as the margin is increased (10% of 33px = 3.3px means container width changes from 33px to 33.3px and so forth). For such computations the resulting behavior is undefined (as pointed out by CBroe).

The browser seems to avoid the loop and sticks with the 30px width. The 3px margin introduced after calculation causes the third link to flow into second row. The browser again avoids the loop by sticking with 30px width.

share|improve this answer

Your Answer


