23

Some HTML code:

<p id='one'>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

<p>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

Some CSS:

#one span {
  display: inline-block;
}

p {
  font-family: Arial;
  font-size: 16px;
  width: 200px;
}

The second paragraph behaves as I expect it.

The first however behaves differently, due to the span being an inline-block.

My question is, why does the inline-block span ignore the &nbsp; and break line between the span and the preceding word?

Thanks!

Example fiddle here.

Sifu
  • 1,082
  • 8
  • 26
Mendel Kramer
  • 357
  • 3
  • 11
  • Because that is what it is supposed to do :) Try putting a border around the elements, and it might make more sense to you. – user1032531 Jul 30 '14 at 16:20
  • 1
    Not sure how [adding borders](http://jsfiddle.net/9G2xE/) explains it. Obviously it's what its supposed to do. I don't think I found a bug in CSS. I just want to understand _why_ it behaves so :) – Mendel Kramer Jul 30 '14 at 16:24
  • You should specify what “behaves” means here. Presumably you mean that a line break appears before the inline element. How do you infer that it appears after the no-break space and not before it? – Jukka K. Korpela Jul 30 '14 at 16:34
  • 1
    @Jukka K. Korpela: Given the use of a no-break space, I would deduce that the expected behavior is that no line break occurs between the word before the inline block, and the inline block. – BoltClock Jul 30 '14 at 16:36
  • @BoltClock, yes, but the question should state that. The answer is probably that an inline block behaves as a single unit, and a no-break space works at the character level – here we have it between a character and an element that acts as a black box in inline formatting. – Jukka K. Korpela Jul 30 '14 at 16:44
  • @Jukka K. Korpela: Indeed, it should be stated in the question. I agree with your explanation but I can't seem to find anything in the specification that confirms this. – BoltClock Jul 30 '14 at 16:52
  • @JukkaK.Korpela: That was precisely my question. I edited to reflect that. I'm having trouble understanding your answer though. Unfortunately, it's hard to find in-depth articles on this topic, and I'm not really interested in reading the spec ;) – Mendel Kramer Jul 30 '14 at 17:08
  • I'd assume because this particular span is a inline-block, it renders the block portion at the edge of the container. Because it is not part of the previous string it is brought down on it's own. Overall this is interesting behavior. – TheHamstring Jul 30 '14 at 17:16
  • Year 2017, I find myself still struggling with this issue, and still no luck :-( – Thariq Nugrohotomo Jan 03 '17 at 07:40

4 Answers4

17

So, it looks like the behavior isn't consistent across browsers:

  • In IE11 and the last few versions I've been able to test this on, whether the span is an inline box or an inline-block box, IE respects the no-break space and does not separate the span from its preceding word.

  • In all other browsers, the behavior is as described in the question. The no-break space appears to be ignored when the span is an inline-block; instead, it gets forced onto its own line and separated from its preceding word. Note that the no-break space is still there; it appears at the end of the first line, just after the word, which can be seen by highlighting the line in Firefox.

The explanation given by some others here seems rather sound: an inline-block is formatted like a block box, except laid inline, so that could be a reason why it doesn't always behave the same as an inline box. However, I haven't been able to find anything in the specification that confirms this. Nor does it explain why IE behaves the way it does, or indeed, whether IE is behaving incorrectly or just differently.

The CSS2.1 spec does state the following in section 9.2.2, which lends itself quite well to the above explanation:

Inline-level boxes that are not inline boxes (such as replaced inline-level elements, inline-block elements, and inline-table elements) are called atomic inline-level boxes because they participate in their inline formatting context as a single opaque box.

But it does not fully describe the interaction between line breaks and atomic inline-level boxes, let alone the effect a no-break space would have on this interaction. So, unfortunately, there does not appear to be a sufficient explanation for the behavior of any one browser.


I've even looked in the CSS3 Text module, but all it has to say with respect to line breaks and atomic inlines is this:

  • The line breaking behavior of a replaced element or other atomic inline is equivalent to that of the Object Replacement Character (U+FFFC).

... and when I try it with a U+FFFC, the results are completely unreliable:

<p id='one'>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

<p>Hello World how are you.&nbsp;<span>Entrepreneur</span></p>

<p>Hello World how are you.&nbsp;&#xfffc;</p>

Namely:

  • IE behaves most consistently, breaking all three paragraphs the same way.

  • Firefox breaks the line with the character the same way as it does the second paragraph, respecting the no-break space.

  • Chrome does not even attempt to render the character.

Maybe I'm just misunderstanding the quote from the CSS3 Text module, maybe browsers aren't implementing certain control characters correctly, I can't say for certain. But, if anything, I'm starting to doubt that this behavior is really defined in any CSS specification at all.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Good analysis. I can't seem to find anything that would indicate that an inline-block introduces a 'soft wrap opportunity' when a regular inline wouldn't. – mrmcgreg Jul 30 '14 at 17:42
  • Thanks for this well-researched answer. I'm going to mark it as accepted, as it best answers the question. – Mendel Kramer Jul 30 '14 at 19:58
4

There does not seem to be any rigorous answer in the specifications, since HTML and CSS specs do not define exact rules for line breaking. HTML 4.01 says: “Sometimes authors may want to prevent a line break from occurring between two words. The &nbsp; entity (&#160; or &#xA0;) acts as a space where user agents should not cause a line break.” But it does not really require that browsers must obey that.

Browsers that do not treat &nbsp; as preventing a line break before an inline-block can justify this by saying that &nbsp; just stands for the NO-BREAK SPACE *character, which is defined (in Unicode) as preventing line breaks when it appears between characters. Here it sits between a character and an inline-block element, which is (informally speaking) to be taken as a black box in line formatting, i.e. it occupies some space but isn’t treated as a character or as containing characters.

Note that the situation is the same if you remove the &nbsp;. A string like “you.Entrepreneur” is not broken, but if you make “Entrepreneur” an inline block, the string may break.

Similar considerations apply to images. Browsers may not honor &nbsp; between text and an image, because here, too, NO-BREAK SPACE does not appear between characters.

You can still prevent line breaks, but you need to be more explicit, e.g.

<p>Hello World how are <nobr>you.&nbsp;<span>Entrepreneur</span></nobr></p>

I’m using nobr in the example for simplicity. You can instead use a standard element and set white-space: nowrap on it (this CSS property, despite its name, does not only affect whitespace handling; this setting prevents line breaks in the content).

Jukka K. Korpela
  • 195,524
  • 37
  • 270
  • 390
1

I would imagine it is due to the inline-block rendering the inside of the element as a block. Since you don't have white space between the text and the span it's forcing a break and then dropping it onto a different line.

Not noticed it before though so it's mainly speculation.

Adam Hughes
  • 2,197
  • 20
  • 31
1

The only thing I can find on this is

According to https://developer.mozilla.org/en-US/docs/Web/CSS/display

For inline-block

The element generates a block element box that will be flowed with surrounding content as if it were a single inline box (behaving much like a replaced element would)

inline

The element generates one or more inline element boxes.

I guess since inline-block generates a block element so the non-breaking space isn't working as expected where a span normally is just inline

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Huangism
  • 16,278
  • 7
  • 48
  • 74