Using soft-hyphenation and truncation to deal with text-zoom.

Using soft-hyphenation and truncation to deal with text-zoom.

For users with low vision, text-zoom is a very valuable tool.  Unlike the browsers default zoom, which scales all content on the page, text-zoom does exactly what the name suggests.  It only increases font size.  This means users aren't forced to scroll excessively to get around image content on your site.  If you want to know what it feels like to use it check-out the zoom text only chrome extension.  Some users will go as high as 800% when navigating a site. I only zoom to 200% when testing a page. That is usually sufficient to determine if there are any issues.

This tool does however introduce new concerns.  Fixed width layouts have a tendency to break. Text will overflow from the fixed width container and even overlap adjacent content.  In practice this occurs when you longer words in your copy or the text is in a narrow content block.

The image below is a list of amazon products shown in a narrow side bar.  The list is enumerated but the numbers are partially obscured by the images next to them.  Additionally the section title is cut-off by overflow: hidden styles on the enclosing container. bestsellers in networking sidebar under 200% text zoom. Heading and list numbers are partially obscured.

In cases like this soft-hyphenation is a very good solution.  It allows you to remove overflow: hidden from the styles. Below is an implementation of soft-hyphenation that I've used in production.

export const chunk = (str, chunkSize = 5) => {
  const results = [];
  let i;
  let len;

  for (i = 0, len = str.length; i < len; i += chunkSize) {
    results.push(str.substr(i, chunkSize));

  return results;

export const softHyphenate = (str, minLength = 10, chunkSize = 5) => {
  const words = str.split(' ');
  return => {
    if (word.length >= minLength) {
      return chunk(word, chunkSize).join('\u00AD');
    return word;
  }).join(' ');

What's a Soft Hyphen?

It a unicode character that is generally invisible under normal circumstances.  It can be injected into the middle of words and will only be visible if that word is breaking on a line.  There is also an HTML entity version of this &shy; Soft HYphen.

My code injects a soft hyphen every 5th character in words that are longer than 10 characters.

Here's what the amazon heading would look like with my script in place.

What about truncation?

Sometimes designs have vertical space constraints and simply wrapping to another line isn't acceptable.  In those cases we can use truncation. Code example below.

export const truncate = (str, userOptions) => {
  const defaultOptions = {
    desiredLength: 20,
    softTruncate: true,
    showEllipsis: true

  const options = Object.assign({}, defaultOptions, userOptions);

  const { desiredLength, softTruncate, showEllipsis } = options;

  if (str.length <= desiredLength) { return str; }

  let trimmedString = str.substr(0, desiredLength);
  if (softTruncate && trimmedString.lastIndexOf(' ') > 0) {
    trimmedString = trimmedString.substr(
      	trimmedString.lastIndexOf(' ')
  return `${trimmedString}${showEllipsis ? '\u2026' : ''}`;

If we applied this code to the amazon heading we would have returned this

Bestsellers in...

Which is useless.

Truncation should be used sparingly and paired with screen reader text.  Often we include a screen reader only version of the full text content where we are truncating.  A low vision user can still potentially see the images and realize that it is network equipment but that isn't reliable enough. Using screen reader text is a good accommodation. Here's an example:

    <span class="sr-only">Bestsellers in Networking</span>
    <span aria-hidden="true">BestSellers in Net...</span>


These two helpers have really been...helpful.  I use them constantly. They are especially useful when dealing with responsive designs and mobile views.  Feel free to steal this code :)