Show hyphens only when necessary? (soft-hyphens doesn't cut it)

CSS 3 includes a "hyphens" property that sets hyphenation accordingly to the specified lang attribute. But it's barely a working draft, so support is kind of not there yet.

You can set it to

  • none, so no hyphens will be shown
  • manual, so it will break words only where the special character &shy was declared, or
  • auto, which would automatically add hyphens where needed according to the localization.

Works like a charm in Firefox, Edge, and even IE, but the main issue is that webkit doesn't support the "auto" value. Except on macs and android, where it's the only value they'd accept. Yup, is that kind of weird bug.

Here's an example, make sure to check the difference between firefox and chrome, if you're running windows / linux.

p { 
  width: 55px;
  border: 1px solid black;
 }
p.none {
  -webkit-hyphens: none;
  -ms-hyphens: none;
  hyphens: none;
}
p.manual {
  -webkit-hyphens: manual;
  -ms-hyphens: manual;
  hyphens: manual;
}
p.auto {
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
  hyphens: auto;
}
<ul>
    <li><code>auto</code>: hyphen where the algorithm is deciding (if needed)
    <p lang="en" class="auto">An extremelyasdasd long English word</p>
  </li> 
  <li><code>manual</code>: hyphen only at &amp;hyphen; or &amp;shy; (if needed)
    <p lang="en" class="manual">An extreme&shy;lyasd long English word</p>
  </li>
  <li><code>none</code>: no hyphen; overflow if needed
    <p lang="en" class="none">An extreme&shy;lyasd long English word</p>
  </li>
</ul>

A common workaround for the lack of "auto" support on webkit is use hyphens:auto together with work-break:break-all for webkit, so text will be hyphened on browsers that supports it and wrap without hyphens on webkit.


Use a container with display: inline-block around the long words.

body { 
  margin-left: 30px;
}
div {
   border: solid 1px black;
}
.wide {
  border: solid 1px blue;
      width: 500px;
}
.narrow { 
  border: solid 1px red;
  width: 360px;
}
 h2 {
   font-family: 'Courier New';
    font-weight: 400;
    font-size: 87px;
  }
code {
 background-color: #eee;
}

.unbreakable {display:inline-block}
<p> <code>Super&amp;shy;man</code> looks good in really narrow containers where the full word "Superman" would not fit</p>
<p>
<div class="narrow"><h2>Hi <span class="unbreakable">Super&shy;man</span></h2></div>

<p>And in this case the word "Superman" would fit unhypenhated on the second row.<br/>
This uses the same code as the previous example</p>
<div class="wide"><h2>Hi <span class="unbreakable">Super&shy;man</span></h2></div>

Edit: Oh, I did find a flaw: words that do break in the wrapper take up all of the two lines rather than allowing shorter words on the same line. In the below example, the text "man is" would have fit on one line if it hadn't been for this trick.

body {
  margin-left: 30px;
}

.narrow {
  border: solid 1px red;
  width: 360px;
}

h2 {
  font-family: 'Courier New';
  font-weight: 400;
  font-size: 87px;
}

.unbreakable {
  display: inline-block
}
<div class="narrow">
  <h2><span class="unbreakable">Super&shy;man</span> is coming.</h2>
</div>

So, no, not perfect. Sorry.