skip to content

PHP: Word Wrapping

PHP: Word Wrapping

In a previous article, we looked at how you can truncate text before displaying it on the page. In those examples. we assumed that the text would be free to wrap as it pleased on the page.

In this article, we look at how you can force text to wrap, and limit it by both line-length and the number of rows.

The wordwrap function

Thankfully, PHP already provides a function for this (almost):

wordwrap -- Wraps a string to a given number of characters using a string break character

Using the same input text as before:

$description = "The World Wide Web. When your average person on the street refers to the Internet, they're usually thinking of the World Wide Web. The Web is basically a series of documents shared with the world written in a coding language called Hyper Text Markup Language or HTML. When you see a web page, like this one, you downloaded a document from another computer which has been set up as a Web Server.";

First we're going to try wrapping the text to a maximum of 40 characters per line:

<?PHP echo wordwrap($description, 40, "<br>\n"); ?>

The World Wide Web. When your average
person on the street refers to the
Internet, they're usually thinking of
the World Wide Web. The Web is basically
a series of documents shared with the
world written in a coding language
called Hyper Text Markup Language or
HTML. When you see a web page, like this
one, you downloaded a document from
another computer which has been set up
as a Web Server.

The result is as one would expect. Now suppose you only want to display three lines of text.

Truncating to a fixed number of lines

The obvious solution would be to truncate to 120 characters and then wrap at 40:

<?PHP echo wordwrap(substr($description, 0, 120), 40, "<br>\n"); ?>

But as you can see, we don't end up with three lines (unless we're very lucky), but four:

The World Wide Web. When your average
person on the street refers to the
Internet, they're usually thinking of
the World

There are two ways to approach the problem. Firstly, you could start reducing the substr length until the text fits onto three lines (in this case to around 110 characters), but for different text, with different length words, that won't always be reliable.

A better approach is to use regular expressions to trim any excess lines:

<?PHP $shortdesc = wordwrap(substr($description, 0, 120), 40, "\n"); preg_match("/(.+\n?){3}/", $shortdesc, $regs); echo nl2br($regs[0]); unset($shortdesc, $regs); ?>

Using the above you can now be certain that you end up with no more than three lines, each with no more than 40 characters:

The World Wide Web. When your average
person on the street refers to the
Internet, they're usually thinking of

Now to clean the code up a bit and put it into a function:

// Original PHP code by Chirp Internet: www.chirpinternet.eu // Please acknowledge use of this code by including this header. function myWrap($input, $chars, $lines = FALSE) { // the simple case - return wrapped words if(!$lines) { return wordwrap($input, $chars, "\n"); } // truncate to maximum possible number of characters $retval = substr($input, 0, $chars * $lines); // apply wrapping and return first $lines lines $retval = wordwrap($retval, $chars, "\n"); preg_match("/(.+\n?){0,$lines}/", $retval, $regs); return $regs[0]; }

Which can be called using:

echo nl2br(myWrap($description, 40)); # wrap at 40 chars echo nl2br(myWrap($description, 40, 3)); # as above, but truncate after 3 lines

The output will be identical to previous examples.

Note: If you're trying to wrap URLs or other text that doesn't contain spaces then you may need to use the cut option of the wordwrap function. To do this you need to modify the code above so that when wordwrap is called you add a fourth parameter - true.

Splitting text evenly into columns

Now to tackle a slightly different problem - how to split a block of text evenly across a number of columns. There used to be a Netscape-specific HTML tag, MULTICOL, which did this within the browser, but it was quickly dismissed by other browser-makers. There are plans to implement something similar in CSS3 but that's not very useful at the moment as so far no browsers are supporting it.

// Original PHP code by Chirp Internet: www.chirpinternet.eu // Please acknowledge use of this code by including this header. function multiCol($string, $numcols) { $collength = ceil(strlen($string) / $numcols) + 3; $retval = explode("\n", wordwrap(strrev($string), $collength)); if(count($retval) > $numcols) { $retval[$numcols-1] .= " " . $retval[$numcols]; unset($retval[$numcols]); } $retval = array_map("strrev", $retval); return array_reverse($retval); }

Below you can see the result of calling this function with the number of columns set to 2, 3 and 4 respectively.

The World Wide Web. When your average person on the street refers to the Internet, they're usually thinking of the World Wide Web. The Web is basically a series of documents shared with the world written in a coding language called Hyper Text Markup Language or HTML. When you see a web page, like this one, you downloaded a document from another computer which has been set up as a Web Server.
The World Wide Web. When your average person on the street refers to the Internet, they're usually thinking of the World Wide Web. The Web is basically a series of documents shared with the world written in a coding language called Hyper Text Markup Language or HTML. When you see a web page, like this one, you downloaded a document from another computer which has been set up as a Web Server.
The World Wide Web. When your average person on the street refers to the Internet, they're usually thinking of the World Wide Web. The Web is basically a series of documents shared with the world written in a coding language called Hyper Text Markup Language or HTML. When you see a web page, like this one, you downloaded a document from another computer which has been set up as a Web Server.

These tables were all generated by a variation of the following code block:

<table> <tr> <?PHP $cols = multiCol($description, 2); foreach($cols as $c) { echo "<td>",htmlspecialchars($c),"</td>\n"; } ?> </tr> </table>

You'll notice there's some trickery going on in the multiCol function, with the string being reversed before being broken into columns, and then reversed back. This is so that we can make sure that any 'overflow' text of the type seen in the preceding discussion on wordwrap can be appended (prepended) to the first rather than the last column.

As you increase the number of columns, you run a risk (because the function isn't perfect) that the overflow will be enough to generate two new columns, but it's hard to imagine a situation on the WWW where it would be necessary to have more than three or four columns on a page.

If you're working with HTML-formatted content then you really need to take into account individual tags and links so that they're not broken in the process of forming columns. This is a much more complicated task.

References

< PHP

Post your comment or question
top