Preventing display of orphans in text using JavaScript

19 September, 2014 by Tom Elliott

Oprhaps in typography, when single words get left on their own line at the end of a paragraph or sentence don’t look great.

widow-line-break-example-1

Example of a widow (or orphan if you prefer)

A graphic designer friend recently asked if there was any way to remove widows that were appearing on some some paragraphs in a recent website project as it was annoying the hell out of him.

My initial response was no.

I tried to explain that some aspects of the web are different from print; that text should be allowed to flow naturally and that we have little control over how website content editors or end users determine how content should be displayed. Users for example may change the font size within the browser, CMS controlled content will vary in length and Responsive Web Design will wrap and break text at different points depending on screen resolution.

But what about post codes for example? Or phone numbers? When these are at the end of paragraphs, it will look even worse if they are broken across multiple lines. Single orphaned words are one thing but broken postcodes will look terrible.

The are a number of ways I’ve considered removing widows in the past. None of which are good solutions. These include:

I then figured that if we could automatically replace a regular space with a   between the two words at the end of a paragraph, this would mean they would get treated as a single word and so would break onto a new line together.

Hooray! With a few lines of jQuery code, we can prevent widows and orphans as shown below:

$('p').each(function(){
    var string = $(this).html();
    string = string.replace(/ ([^ ]*)$/,' $1');
    $(this).html(string);
});

This will loop through each paragraph on the page, search for the last space in the string using a Regex pattern and replace the space with a non-breaking-space  . The original paragraph is then replaced with the new string, with the non breaking space between the last two words or two text strings.

Searching through every p tag on the site however might be overkill. You might just want to target a particular paragraph or heading. For example the below will loop through each paragraph within a ‘main-post’ div and each h2 tag:

$('#main-post p, h2').each(function(){
    var string = $(this).html();
    string = string.replace(/ ([^ ]*)$/,' $1');
    $(this).html(string);
});


10 Comments

  • Al says:

    Thanks for the tip – the designers in the office will be very happy!

  • Matthew says:

    Thank you. Very elegant and efficient. I am working on a book selling website with many variable text lengths to where it would be impossible to edit every one. Also things like book titles are non editable. So for book titles this will work well since some can be quite long even without subtitles.

  • Jon Ewing says:

    Great idea – worked perfectly – many thanks.

  • Ash says:

    I found that if you have this on a tag with a single link in it, it actually adds the   into the a tag, breaking it.

  • Ert says:

    I implemented this on a blog index page, where each short summary is ended with a link to read “more” – it did not break the links, they seem to work fine with an nbsp dropped in there, but since it was not applied to the rendered last space in the visible text, instead to the last space in the code… I still got orphans. *sob*

    Works perfectly where there is no code at the end of a paragraph. Neat!

    • Clare Goult says:

      To add the nbsp on links at the end of paragraphs replace:
      string = string.replace(/ ([^ ]*)$/,’ $1′);

      with:
      string = string.replace(/\s([^\s<]+)\s*$/,' $1');

  • Clare Goult says:

    Oops, that doesn’t work, I meant this.

    string = string.replace(/\s([^\s]+)\s*$/,’ $1′);

    • Clare Goult says:

      Never mind. That doesn’t seem to work either when I looked on another page I’d built. Oh well. Perhaps add the JS to the page with links at the end and then copy the source so you don’t have to add them manually and then delete the JS. Not an ideal solution by any means.

  • Lord Heyns says:

    string = string.replace(/\s(?=[^\s]*$)/g, ” “);

    Ha, the title of this page had a single word on the second line. I thought that was intentional until I scrolled. You gotta practice what you
    preach!

    PS: Not all denominations allow preachers to be women (so calling the word above a widow may offend some church goers). The non-gender term orphan is more universal.