Headline Balancing Act

This post was originally published on this site


The New York Times can be read on your phone, tablet, laptop, and on many other networked screens, and it’s impossible to know in advance how every headline appears on every display. Sometimes, the headline wraps just fine. But there are many times when they don’t, introducing unsightly widows. Even when there aren’t strict widows, instances where one line is dramatically shorter than others can still hurt legibility and reading flow.

These blemishes are easily fixed in print. On a fixed canvas, we can fit copy to fill a space, and designers can work with editors to get the text to behave just right. On the web, where space is dynamic, we can’t adjust layouts by hand. But that doesn’t mean we have to just accept bad typography, we just have to use a different approach: translate and codify good design guidelines (which can be intuitive and circumstantial) into a concrete, reusable set of instructions.

We have made several attempts to tackle this problem. For a while, we were relying on Adobe’s balance-text jQuery plugin on special feature articles. While the result looked great, performance was not ideal: sharp-eyed readers would see the headline update after the page’s fonts loaded. And since the headline is one of the first things someone will look at, this was not great.

The previous jQuery plugin (from Adobe) in action.

So during our Maker Week last summer, I suggested coming up with a more robust headline balancer that could be used anywhere — not just special features. After seeing some examples of bad wrapping, a few engineers agreed to search for a better solution. The winning idea came from one of our interns, Harrison Liddiard. He came up with a lightweight implementation (without a jQuery dependency, even!) that gave us what we were looking for.

Michael Beswetherick proceeded to make this script ready for production. Combing through hundreds of headlines of varying lengths, we measured the effectiveness and efficiency of our balancer, adjusting based on what we saw. You can see the before/after for just a few of the headlines:

And now … it can be yours

We’re more than a little excited to release our work on Github. Now, we realize that a piece of code that only works on headlines might not be very useful, so we’ve abstracted our solution and named it text-balancer:

https://github.com/NYTimes/text-balancer (and also, an npm module)

(Now, remember: moderation is best in all things. You should apply this selectively, not to everything you can get your hands on. We suggest headlines, blockquotes, and other places where you’re using large display type. We do not recommend using this on body type, buttons, or navigational links.)

Wondering how text-balancer actually works? Well, it’s a binary search algorithm applied against a text element’s max-width. We then adjust its max-width until the element squeezes right up to the point that it spills onto another line.

Here it is in action: (slowed down so you can see how it works)

We calculate the max-width to be the average of a bottom range that starts at 0 and changes depending on whether the updated max-width makes the text fall onto another line.

One of the more subtle aspects of text-balancer is that the text element will always remain the same number of lines that it was before. It will also re-adjust when the browser size changes; all you need to do is set it up once and you can rest assured that the text will always be balanced.

One Last Thing

When we were first testing it, we kept noticing that our text look…well, didn’t actually look balanced. Finally, we figured out that we were using text-balancer before the headline font had finished loading. So: you should wait to run text-balancer until after your fonts have loaded.

We looked for a way to detect when our fonts had loaded and came across Bram Stein’s https://fontfaceobserver.com/. Calling the observer’s load method returns a promise that will tell us the right time to balance our text.

const chelt = new FontFaceObserver('cheltenham');
chelt.load().then(() => {
console.log('fonts have loaded yay');

What Else?

In the future, we’d like to be able to place line breaks with awareness to style guide conventions: not splitting within names and phrases, not splitting after a lowercase word, and so on. (If someone wants to add this and send in a pull request, we won’t say no.)

In the meantime, give text-balancer a try and let us know what you like or don’t like!

A balanced headline on an NYTimes.com article.

Headline Balancing Act was originally published in Times Open on Medium, where people are continuing the conversation by highlighting and responding to this story.

Comments are closed.

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑