Although I wasn’t able to attend, I was very excited to follow the recent An Event Apart conference in Minneapolis via Twitter and notes posted by attendees. One thing that caught my eye was Richard Rutter’s talk, ‘Detail in Web Typography’, and a couple of tweets (1, 2) that mentioned CSS-based hyphenation. It turns out that the latest versions of some browsers support hyphenation with the following CSS:
Update : Firefox 6 got released as I was writing this yesterday, so there are now two browsers available supporting CSShyphens, Firefox 6 and Safari 5.1.
Testing for support
For many, the broken find-on-page might not be a big enough reason to avoid using Hyphenator.js, but others may not want to lose that functionality. Luckily, not all browsers break in this way, and we can test for proper full support before applying Hyphenator.js.
The test_wordbreak() function above takes a string as an argument and uses that string as a delimiter between two characters. With this function we can test ­ (or Á) and zero-width space delimiters to see if browsers acknowledge them and properly wrap text to a new line. We test for this by measuring the height of the container without the delimiter to get the height of a single line of text, then by measuring the height of the container with the delimiter. If the second measurement is larger, we can be reasonably sure that the text has been wrapped to a second line. It’s a little hacky, but it works.
This function works well in most browsers. However, some browsers that I’ve tested (specifically on BlackBerry devices, including the PlayBook) will recognize the soft hyphen and wrap the text properly, but won’t display the hyphen itself. For this reason, we need to modify the function above to also test for the width of the container.
As before, if the width of the container with the soft hyphen is larger than the width without, we can be reasonably sure there is an extra visible hyphen being displayed.
These tests tell us whether the browser recognizes and uses the soft hyphen properly, but not whether they break the find-on-page functionality. To test that, we’ll need another function that injects some text with a delimiter, and then searches for that text without the delimiter. If the text is found, we know that find-on-page is not broken; if not, it is broken.
By combining the functions in Figures 3 and 4, we can get a pretty good idea if it’s safe to use Hyphenator.js in a browser.
Problems and Browser Support
Naturally, life for a web developer is never that easy.
First, there’s the issue of Chrome’s support for the hyphensCSS. Unfortunately, Chrome claims that it supports this hyphenation, but in actual fact no hyphenation occurs. This is a problem if we want to test for CSS support before applying Hyphenator.js.
The solution to this is even more hacky than the functions above, but it should work.
Basically, this throws a huge wad of text into an element and sees if the element changes size when hyphenation is applied. Like I said, hacky.
This kind of false positive means that Hyphenator.js will be applied even though using it will break find-on-page. Options for dealing with this are unappealing:
Accept that find-on-page is broken on these devices.
Do browser sniffing in the test to make sure Android browsers don’t have Hyphenator.js
Give up on the whole thing entirely.
Wrapping it all in Modernizr
Modernizr is amazing and should be part of every web dev’s toolkit. Not only does it have a great built-in battery of tests for feature support, it also allows us to add our own. We can use Modernizr’s addTest() API to get very robust support for hyphenation on the web, without breaking anything in older browsers.
These tests will check for both CSS hyphenation support and Hyphenator.js soft hyphen/zero-width space support. The results of these tests will allow us to dynamically apply different styles and JS libraries based on what the user’s browser supports.
If CSS hyphenation is supported, it will be applied; browsers that don’t recognize the CSS hyphenation rules will simply ignore them.
If CSS hyphenation is not supported, but soft hyphens and the zero width space are, we’ll load and apply Hyphenator.js.
If neither are supported, the page remains unhyphenated but functional.
If you’d like to test this out for yourself in your own browser, feel free to check out this demo page and let me know your results, either in a comment, by email or via Twitter.
This is pretty basic right now, and is more of a proof-of-concept. I definitely welcome feedback and improvements. I’ve forked Modernizr on GitHub and have added this as a feature-detect, so feel free to fork it yourself and make it better! (Especially if you have a fix for the Android problem!) [Note: my feature test has now been pulled into the main Modernizr repo, so you can also mess around with it there].
Updated to mention Firefox 6 release
Updated to fix a syntax error in Figure 6
Updated to add window.scroll(0,0) in Figure 6 and update GitHub note
Updated to fix soft hyphen and ZWS characters that weren't appearing correctly in the code