The fine art of hyphenation

Long words can easily break your layout, especially in languages like German with lots of compound words. You don’t even need a “Donau­dampfschiff­fahrtsgesell­schafts­kapitän” if the word is in a big headline on a small screen.

In this article I want to share what I’ve learned about this topic over the last years.

Automatic hyphenation in the frontend

It surely would be great to just add a few lines of code and consider it done. Unfortunately, it’s not that easy. But let’s have a look at the simplest solution first.

You don’t need much to enable automatic hyphenation in the frontend. Just set your HTML lang attribute correctly and add the following CSS:

.text {
  hyphens: auto;
}

Browser support is good nowadays, but hyphenation quality unfortunately isn’t. Sometimes you’ll see too many hyphenated lines in a row. Other times automatic hyphenation produces “leg-endary” breaks that can confuse readers. It might be worse in German but I’ve seen it in English as well.

Here’s an example of how Google Chrome hyphenates a German text:

A text paragraph in German showing hyphenation points marked in red. Words that are hyphenated include

During my apprenticeship at a print magazine a long time ago, I learned about hyphenation the hard way. After accidentally hyphenating “Klosterfrau” (roughly translated to “nun”) as “Klo-sterfrau” (where “Klo” means toilet) in a printed issue, they made me double-check every single hyphenation from then on. Some lessons you never forget 🚽

Taking more control on the server

For more control, you can handle hyphenation on the server using libraries like Syllable for PHP. They add soft hyphens based on syllables and language rules.

Among other settings, you can set minimum word lengths to prevent excessive hyphenation:

$syllable->setMinWordLength(10);

If you’re using Kirby, you might want to have a look at my plugin kirby-hyphenate.

In the example image above, the words “Zeitplan”, “arbeitet”, “zusammen”, and “beheben” would not be hyphenated with a minimum word length of 10.

It’s still automatic, though. No matter how good the library is, it can’t know the context of your text (at least I haven’t seen a library that can).

Manual hyphenation

In my experience, manual hyphenation is the most reliable way to handle long words. It’s also the most time-consuming, but it’s worth it. Let’s look at our options:

Adding soft hyphen HTML entities

The easiest way is to use the ­ HTML entity to add invisible soft hyphens that only wrap words when needed. That’s what the above mentioned library does, too. It can make text in the backend quite un­read­able, though.

Making the HTML entity more readable

For a very long time, I simply converted (-) into ­. This makes the soft hyphens easier to type and the text stays relatively read(-)able.

Using Kirby, it’s quite easy with a kirbytags hook:

Kirby::plugin('medienbaecker/shy', [
    'hooks' => [
        'kirbytags:before' => function ($text, $data, $options) {
            return Str::replace($text, "(-)", "­");
        }
    ]
]);

Using the unicode character directly

Depending on how excessively you hyphenate, even the (-) might go on your nerves. It would be great to toggle visibility of the soft hyphens like in professional editorial software, right?

Just use the unicode character for soft hyphens U+00AD directly!

You can copy it from sites like Unicode Explorer or setup a shortcut or Raycast snippet like I did.

I’ve recently found this great Kirby plugin called Typo & Paste that makes it easy to insert special characters. It’s a great alternative for less tech savvy editors.

Then, depending on your text editor or content management system of choice, you can toggle the visibility of invisible characters on and off.

Because it can look very different depending on the tool, here’s a simple visual representation:

A German text paragraph with an Invisibles button above it.
A German text paragraph with an Invisibles button above it. The button is orange and the invisible characters are visible.

This way you can also identify non-breaking-spaces and other invisible characters.

In Kirby you can use the markdown field’s invisibles button or the kirby-hidden-characters plugin for other fields. I love how there are so many typography-related plugins for Kirby!

The soft skills around soft hyphens

Often it’s the editor, not yourself who has to do the (manual) hyphenation. Therefore it’s important they know how and when to hyphenate.

In some projects in the past I used a simple plugin for Kirby’s markdown field that visually highlights long words. This way editors could see at a glance where they might want to add soft hyphens:

A screenshot of the Kirby markdown field with long words highlighted in orange.

In the case of the markdown field, it’s actually quite easy to add custom highlights.
You just need a tiny bit of PHP:

<?php
Kirby::plugin('medienbaecker/lengthy-word-locator', [
  'fabianmichael.markdown-field.customHighlights' => [
    [
      'name'       => 'lengthy-word',
      'regex'      => '\b[\wäöüÄÖÜß]{20,}\b',
      'class'      => 'lengthy-word',
    ],
  ]
]);

Then you can style the highlights with CSS:

.lengthy-word {
  background-color: rgba(255, 128, 0, 0.25);
}

Finding what works for you

In most projects right now, I’m using completely manual hyphenation while trying to make it as easy as possible for editors to handle this themselves. I also make sure to talk to them about the importance of hyphenation and how to do it.

This article ended up being something of a chronological journey through my experiences with hyphenation – from automatic solutions to server-side processing, and finally to manual hyphenation with proper tooling. Not the most structured article perhaps, but an honest reflection of how I learned to deal with long words in web typography.

If you have your own experiences or tools to share, I’d love to hear about them on Mastodon.