139

Let's say I have this text that I want to display in an HTML table cell:

Honey Nut Cheerios, Wheat Chex, Grape-Nuts, Rice Krispies, Some random cereal with a very long name, Honey Bunches of Oats, Wheaties, Special K, Froot Loops, Apple Jacks

and I want the line to break preferentially after one of the commas.

Is there a way to tell the HTML renderer to try breaking at some designated spot, and do that first before trying to break after one of the spaces, without using non-breaking spaces? If I use non-breaking spaces then it makes the width larger unconditionally. I want the line break to happen after one of the spaces, if the line-wrapping algorithm has tried it with the commas first and can't get the line to fit.

I tried wrapping text fragments in <span> elements but that doesn't seem to do anything helpful.

<html>
  <head>
      <style type="text/css">
        div.box { width: 180px; }
        table, table td { 
          border: 1px solid; 
          border-collapse: collapse; 
        }
      </style>
  </head>
  <body>
    <div class="box">
      <table>
      <tr>
          <td>lorem ipsum</td>
          <td>lorem ipsum</td>
          <td>lorem ipsum</td>
      </tr>
      <tr>
          <td>lorem ipsum</td>
          <td>
            <span>Honey Nut Cheerios,</span>
            <span>Wheat Chex,</span>
            <span>Grape-Nuts,</span>
            <span>Rice Krispies,</span>
            <span>Some random cereal with a very long name,</span>
            <span>Honey Bunches of Oats,</span>
            <span>Wheaties,</span>
            <span>Special K,</span>
            <span>Froot Loops,</span>
            <span>Apple Jacks</span>
          </td>
          <td>lorem ipsum</td>
      </tr>
      </table>
    </div>
  </body>
</html>

note: It looks like the CSS3 text-wrap: avoid behavior is what I want, but I can't seem to get it to work.

Kalnode
  • 9,386
  • 3
  • 34
  • 62
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • you can use *non-breaking-spaces* inside the spans. – Gabriele Petrioli Mar 22 '11 at 14:35
  • 8
    But I don't want to use *non*-breaking spaces. I'd love to use "don't-want-to-break-here-but-I-will-if-I-have-to" spaces, but as far as I know, those exists. – Jason S Mar 22 '11 at 14:44
  • @Jason.. i feel you .. but it is not possible .. added an answer. – Gabriele Petrioli Mar 22 '11 at 14:47
  • drat, that's what happens when computer scientists write rendering algorithms w/o input from typographers. – Jason S Mar 22 '11 at 15:10
  • 1
    you should accept the answer from @EggertJóhannesson as it provides a good workaround! – Gabriele Petrioli Oct 16 '14 at 17:31
  • done (sorry, I don't keep watch on old questions very often). https://jsfiddle.net/kqa8p1f4/2/ vs. https://jsfiddle.net/kqa8p1f4/1/ – Jason S May 12 '15 at 16:01
  • I know its been several years, but I have another solution that works. If used in combination with any of the `` hacks, the *line-breaking algorithm* will be completely overruled –  Mar 02 '16 at 08:33

9 Answers9

187

By using

span.avoidwrap { display:inline-block; }

and wrapping the text I want to be kept together in

<span class="avoidwrap"> Text </span>

it will wrap first in preferred blocks and then in smaller fragments as needed.

grg
  • 5,023
  • 3
  • 34
  • 50
Eggert Jóhannesson
  • 1,886
  • 1
  • 12
  • 2
  • 21
    Works great! Just one additional note: spaces at the start and the end of an inline-block are ignored, so that to delimit text in blocks by space you need to place it between inline-blocks. For example, if spans were styled to become inline-blocks, then `Hello world` will be `Helloworld`, and `Hello world` will be normal `Hello world`. – user Mar 20 '14 at 22:35
  • 5
    is more semantic and leaves control in the browser, which is generally a good thing. In this case it makes breaking-when-vital possible. – Lodewijk Aug 14 '14 at 01:29
  • Works great - when it is important, that chars like "-" non break. Example: Perikles (um 500-429 v.Chr.) – Sarah Trees May 19 '15 at 17:37
  • 12
    @Lodewijk: `` does not indicate a *preferred* place to break the line, but a *possible* one. – Dan Dascalescu Jul 09 '15 at 03:52
  • this will still break on hyphens and other special characters. If your solution is used in combination with mine, the *line-breaking algorithm* will be completely taken over –  Mar 02 '16 at 08:29
  • 3
    Note that this technique works for nested ``s too, so you can (in effect) specify a *hierarchy* of preferred breakpoints. – Michael Dyck Nov 07 '16 at 16:35
  • avoidwrap also happean if `white-space: nowrap;` rule set – Alex Szücs May 30 '22 at 16:55
32

There's a very neat RWD-solution from Dan Mall that I prefer. I'm going to add it here because some other questions regarding responsive line breaks are marked as duplicates of this one.
In your case you'd have:

<span>Honey Nut Cheerios, <br class="rwd-break">Wheat Chex, etc.</span>

And one line of CSS in you media query:

@media screen and (min-width: 768px) {
    .rwd-break { display: none; }
}
Declan McKenna
  • 4,321
  • 6
  • 54
  • 72
Stephan Weinhold
  • 1,623
  • 1
  • 28
  • 37
13

An easy answer is to use the zero-width space character &#8203; It is used for making breakspaces inside words at specific points.

Does the exact opposite of the non-breaking space &nbsp; (well, actually the word-joiner &#8288;)(word-joiner is the zero-width version of non-breaking space)

(there are also other non breaking codes like the non-breaking hyphen &#8209;)(here is an extensive answer on different 'variants' of nbsp)

If you want an HTML-only (no CSS/JS) solution you could use a combination of the zero-width space and the non-breaking space, however this would be really messy, and writing a human-readable version requires a little effort.

ctrl + c, ctrl + v helps

example:

   Honey&nbsp;Nut&nbsp;Cheerios,<!---->&#8203;<!--
-->Wheat&nbsp;Chex,<!---->&#8203;<!--
-->Grape&#8209;Nuts,<!---->&#8203;<!--
-->Rice&nbsp;Krispies,<!---->&#8203;<!--
-->Some&nbsp;random&nbsp;cereal&nbsp;with&nbsp;a&nbsp;very&nbsp;long&nbsp;name,<!---->&#8203;<!--
-->Honey&nbsp;Bunches&nbsp;of&nbsp;Oats,<!---->&#8203;<!--
-->Wheaties,<!---->&#8203;<!--
-->Special&nbsp;K,<!---->&#8203;<!--
-->Froot&nbsp;Loops,<!---->&#8203;<!--
-->Apple&nbsp;Jacks

unreadable? this is the same HTML with no comment tags:

   Honey&nbsp;Nut&nbsp;Cheerios,&#8203;Wheat&nbsp;Chex,&#8203;Grape&#8209;Nuts,&#8203;Rice&nbsp;Krispies,&#8203;Some&nbsp;random&nbsp;cereal&nbsp;with&nbsp;a&nbsp;very&nbsp;long&nbsp;name,&#8203;Honey&nbsp;Bunches&nbsp;of&nbsp;Oats,&#8203;Wheaties,&#8203;Special&nbsp;K,&#8203;Froot&nbsp;Loops,&#8203;Apple&nbsp;Jacks

However, since email html rendering is not completely standardized, its good for that kind of use since this solution uses no CSS/JS

Also, if you use this in combination with any of the <span>-based solutions, you will have complete control of the line-breaking algorithm

(editorial note:)

The only problem I could see you having is if you wanted to change the points of preferred breakage dynamically. This would require constant JS manipulation of each of the spans proportionate size, and having to handle those HTML entities in the text.

Community
  • 1
  • 1
  • 1
    what are span hacks? – Jason S Mar 02 '16 at 13:34
  • The other answers taking advantage of span tags. –  Mar 02 '16 at 13:35
  • I want to also note that while this solution doesn't seem to be the simplest, it is the most dependable, because those entities do not and should not change semantic representation often across browsers, email parsers, or any other HTML parser. –  Oct 30 '16 at 04:48
  • 2
    You could run into problems if the text you're breaking is copied and parsed somehow - then the extra digit might be in the way. If you try to break an email at the @, copy and paste would fail with no clue to the user why not. If you expect the data to be read by crawlers or copy pasted, I wouldn't advice this solution. – isacvale Aug 21 '20 at 13:59
8

The thing that you're supposed to do (use Unicode for what it was intended) provides the best results:

enter image description here

<table border="1">
  <thead>
    <tr><th>Method</th><th>Results</th></tr>
  </thead>
  <tbody>
    <tr><td>&lt;wbr></td><td>Honey Nut Cheerios,<wbr> Wheat Chex,<wbr> Grape&#8209;Nuts,<wbr> Rice Krispies,<wbr> Some random cereal with a very long name,<wbr> Honey Bunches of Oats,<wbr> Wheaties,<wbr> Special K,<wbr> Froot Loops,<wbr> Apple Jacks</td></tr>
    <tr><td>U+200B Zero width Space</td><td>Honey Nut Cheerios,&#8203;Wheat Chex, &#x200b;Grape&#8209;Nuts, &#x200b;Rice Krispies, &#x200b;Some random cereal with a very long name, &#x200b;Honey Bunches of Oats, &#x200b;Wheaties, &#x200b;Special K, &#x200b;Froot Loops, &#x200b;Apple Jacks</td></tr>
    <tr><td>U+00A0 No&#8209;break Space</td><td>Honey&nbsp;Nut&nbsp;Cheerios, Wheat&nbsp;Chex, Grape&#8209;Nuts, Rice&nbsp;Krispies, Some&nbsp;random&nbsp;cereal&nbsp;with&nbsp;a&nbsp;very&nbsp;long&nbsp;name, Honey&nbsp;Bunches&nbsp;of&nbsp;Oats, Wheaties, Special&nbsp;K, Froot&nbsp;Loops, Apple&nbsp;Jacks</td></tr>
  </tbody>
</table>
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
2

With your mark-up above use span { white-space:nowrap }. It's as good as you can expect really.

Marcel
  • 27,922
  • 9
  • 70
  • 85
  • Thanks, but that won't work because it basically translates spaces within a `span` element to ` `, and keeps the spaces from breaking at all. I just want to discourage the renderer from breaking in between one of my items, but if it has to, I want it to do so. – Jason S Mar 22 '11 at 14:46
  • @Jason S: I've added other options to my answer. – Marcel Mar 22 '11 at 14:57
  • how is ` ` any different than a space? From what I can tell, the choices are either that a given character allows a break or does not. So '-' and ' ' and `​` and `` and `­` all allow a break (printing a hyphen, space, nothing, nothing, and hyphen-only-on-break, respectively), whereas ` ` does not. – Jason S Mar 22 '11 at 15:08
  • @Jason S: Added example usage. – Marcel Mar 22 '11 at 15:17
  • I just tried it, and it doesn't seem to take priority over spaces for line-breaking. The priority is what I need. If the breaking behavior for a different character or element is either yes or no, then there is no solution for my problem. If there are relative line-breaking priorities, then I might have a solution. – Jason S Mar 22 '11 at 15:20
  • OK, I just went way off track and realised I was talking about `` like it meant 'preferential line-break` if needed or something. Stripping useless information from my answer now, off to bed. – Marcel Mar 22 '11 at 15:27
2

The answer is no (You cannot alter the line breaking algorithm used).

But there are some workarounds (best one is the accepted answer)

You can go near with the non-breaking-space &nbsp; but only between words that go together (what you have in spans, but not after the comma ), or you can use the white-space:nowrap as @Marcel mentioned.

Both solutions do the same thing, and both will not break a group of words if it does not fit on its own.

Community
  • 1
  • 1
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • argh. :-( that stinks, it means I either have to live with it, or I need to try to detect long lines on my own in an attempt to defeat the line-breaking algorithm. – Jason S Mar 22 '11 at 14:48
  • I edited your answer to provide a link to the workaround, since I almost didn't continue reading because of the way your first line is phrased. – Matt Mills Jan 13 '15 at 19:41
  • @arootbeer: I support your edit, but Gaby reverted it. Gaby: why? Do you want to mislead users? – Dan Dascalescu Jul 09 '15 at 03:53
  • @DanDascalescu, should all answer is SO be changed to point to the accepted one in the same page? My answer has 1 (*sum*) vote and there is an accepted answer with 48 votes. I am pretty sure that the accepted one is the one getting the attention (***and rightly so***). Besides that, i insist that there is not way to change the breaking algorithm used (*as the OP asks for*) – Gabriele Petrioli Jul 09 '15 at 11:35
  • You're committing the false dichotomy and slippery slope fallacies. Most answers on SO are alternative ways of achieving a result. A subset make false statements. Those, yes, I would suggest the authors show they care about truth and their fellow users, and amend the answers. At your rep, I would expect that. – Dan Dascalescu Jul 09 '15 at 12:05
  • @DanDascalescu i still disagree, but since you both find it important i added it back. – Gabriele Petrioli Jul 09 '15 at 14:13
  • 1
    check my solution uses your own logic against you. combine that with any of the span solutions, then you have complete control of the line-breaking algorithm –  Mar 02 '16 at 08:07
0

New answer now we have HTML5:

HTML5 introduces the <wbr> tag. (It stands for Word Break Opportunity.)

Adding a <wbr> tells the browser to break there before anywhere else, so it's easy to make words break after commas:

Honey Nut Cheerios,<wbr> Wheat Chex,<wbr> Grape-Nuts,<wbr> Rice Krispies,<wbr> Some random cereal with a very long name,<wbr> Honey Bunches of Oats,<wbr> Wheaties,<wbr> Special K,<wbr> Froot Loops,<wbr> Apple Jacks

It is supported my all major browsers apart from IE.

ACarter
  • 5,688
  • 9
  • 39
  • 56
  • 15
    -1. Why didn't you test before advising? It doesn't work. [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr) has another purpose. Not to mention that this answer is a duplicate of an [answer](http://stackoverflow.com/questions/5392853/html-css-denoting-a-preferred-place-for-a-line-break#5393305) that existed long before. – user Mar 20 '14 at 14:17
  • 2
    WBR does not have another purpose. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr – Lodewijk Aug 14 '14 at 01:28
  • 1
    But nobody knows where the 'r' comes from ! – Lodewijk Aug 14 '14 at 01:28
  • 17
    `` just sets up a break opportunity; it does not “tell the browser to break there before anywhere else”. Used before a space, it is normally useless, since spaces are normally line break opportunities. – Jukka K. Korpela Sep 24 '14 at 06:03
  • Great! Thanks so much! I hadn't heard of this at all. I think this is the real answer to the op. – JohnK Jul 10 '15 at 14:13
  • This should be marked as answer. I don't understand why the downvote. – alejosoft Oct 05 '15 at 14:46
  • Not supported by safari mobile. – Mark Dec 07 '15 at 16:45
  • 7
    This doesn't work at all, in any browser. The answer is wrong: `` does *not* prioritize a line break over ordinary whitespace. So wrapping just happens as normal in the example. – adrian Jan 07 '16 at 18:32
  • 5
    To clarify, is intended to signal "here is a place you can break", when that position would otherwise be considered _inside a word_. It says "treat the spot between these two characters as if there were a space there", not "prefer to break here". If there’s already a space, has no meaning. – Semicolon Sep 11 '17 at 02:07
-3

You can just adjust the margin settings in CSS (margin-right in this case).

text {
    margin-right: 20%;
}
gooflord
  • 5
  • 3
-3

Use <div> instead of <span>, or specify a class for SPAN and give it the display:block attribute.

justacoder
  • 2,684
  • 6
  • 47
  • 78