In Chromium 96 on Mac there’s a bug where it will show box characters instead of hyphens. It doesn’t happen with all fonts, but it happens enough to notice. Awaiting a patched Chromium 98, we can use some CSS to fix it.
~
# The Bug
Here’s (a screenshot of) a Pen that has the font set to Arial and has hyphenation enabled:
(Click image to go to interactive Pen)
The hyphenation itself will work as expected, but for some reason — which we’ll detail below — it shows box characters where the hyphens should be.
The CSS powering the Pen are the 100 bytes of CSS to make any page look good, along with this little snippet:
body {
font-family: arial;
hyphens: auto;
}
The bug happens in Chromium-based browsers on Mac — That’s Google Chrome, Microsoft Edge, Brave, etc. It only happens on macOS Monterey; Big Sur does not show this bug.
~
# Digging Deeper
Searching around I found Chromium Bug #1267606 which covers the bug. In it, Chromium Engineer Dominik Röttsches (drott) dug deeper and unearthed the details.
There are two hyphen characters,
U+2010
(HYPEN) andU+002D
(HYPHEN-MINUS) […]Our hyphenation code first looks for
U+2010
in the font, otherwise usesU+002D
.
Even though Arial has no U+2010
set, the Core Text API — which is used to retrieve the glyph — claims there is:
The new and old version of the font do not have hyphens in their cmap table, but the CoreText function for retrieving a glyph id does strangely return
16
forU+2010
on Monterey, but doesn’t find the glyph in the font on Big Sur (as it should).
And when a font tries to show a glyph it does not have, it’ll show a box instead.
~
# The workaround
The bug itself has already been patched, and the patch is included in Chromium 98 which is due Feb 1, 2022. If you can’t wait until then, there’s a CSS workaround that you can use: the hyphenate-character
property
This property specifies the string that is shown between parts of hyphenated words.
For WebKit (which powers Safari) and Blink (which powers Chromium) you need to use the vendor-prefixed -webkit-hyphenate-character
variant, so the CSS fix becomes this:
html {
-webkit-hyphenate-character: '-';
}
Easy, peasy 🙂
~
Side Note: at the time of writing no browser supports the unprefixed hyphenate-character
property. There seems to be interest from Gecko (Firefox’s Rendering Engine) on it though, as they’ve recently asked if the spec work on it stable enough, before starting work on it.
See the Pen CSS hyphenate-character / -webkit-hyphenate-character Support test by Bramus (@bramus) on CodePen.
UPDATE: As reader Šime Vidas points out, Firefox Nightly (version 97.a1) supports hyphenate-character
, the first browser to do so 🎉
I’ve filed bugs with WebKit and Blink to unprefix their implementation.
~
Thank me with a coffee.
I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
This is incredible! Thanks, totally solved the issue. Took awhile of searching before I found your article, but it was exactly what I needed. A reason and explanation. Big appreciation!
Thank you for sharing your solution!
As of March 23, 2023, this bug still hasn’t been fixed for Chromium browsers.
I am experiencing the sam bug with the NON-BREAKING hyphen (U+2011) – sadly the fix does not seem to work for this
Yeah, I’m the author of the noted Chromium bug #1267606. I’ve been dutifully posting updates as version after version of Chrome are being released, with no change to this annoying bug. Please star the issue so it gets more attention!
https://bugs.chromium.org/p/chromium/issues/detail?id=1267606
The bug has been fixed at long last, in Chrome 111.
Argh – – just implemented your suggested fix and it doesn’t work 🙁 Any other options you know of to force it to work? Any inline css or code that could resolve in a few instances where this appears?
March 2023 workaround for non breaking hyphen (U+2011):
You just need a fallback font that is something other than Arial like this:
font-family: $my-custom-font, Helvetica, sans-serif;
I use “font-display: swap” so it loaded first Arial, which destroyed the hyphen and then changed it. Which resulted in nothing.
With the fallback it’s changing to Helvetica which renders a hyphen and then gets changed to my custom font.