Not too long ago I was asked to support with some PDF rendering issues in one of our projects. In particular we were facing two common problems - word-wrap not working in Visualforce PDFs, and the loss of styling when using “Arial Unicode MS” font family.
I plan to write two blog posts about these problems with the solutions we implemented to get around them. This first post will be about the issue with word-wrap: break-word not playing nice.
Before and After photos
In order to demonstrate the problem and the solution, I’ve created a 4 column HTML table with some very long words inside of it. Here is how the table looks like when it is rendered in a Visualforce page as a PDF:
And here is how the same table looks like inside the same Visualforce page after some Apex magic:
Why is this happening?
The main problem we are facing is that Salesforce Visulaforce PDFs are using a very old PDF rendering engine called Flying Saucer which has a very limited support for CSS 3 features and the word-wrap is not one of them.
I learned this by reading through questions and answers in this StackExchange post when I first encountered this issue. On that same StackExchange post I’ve read the answer from Ralph Callaway that I used as a starting point for the solution I will present here.
How to solve it?
The basic concept of the solution is that the long words must be broken down so that they are automatically wrapped by the PDF rendering engine. The best way to split them is to wrap them with <span> tags so that a word such as SomethingVeryLong is represented as <span>Somethi</span><span>ngVeryL</span><span>ong</span>.
The Visualforce page rendering engine can then use the span elements to split the word if it needs to, and the best part is, if it does not have to split it, the PDF will render it normally.
The Code
The below code snippet contains the complete solution for breaking the long words into individual span elements:
The code will apply the avoid-wrap CSS class to the span elements that represent the complete word that was split. Because of that, it’s always good to include the following CSS in your Visualforce Page to tell it not to wrap that span unless it really needs to:
Additionally, the code will try to be “smart” when splitting the words and try to split them at special characters (e.g. -;:<>/\\\u00A0).
How to use the code?
Let’s say you have an Apex controller with a getter called getHtml() that returns some HTML back to the Visualforce page. All you need to do is pass that HTML code through the stringReducer() function before returning it:
For the sake of completenes, here is the Visualforce Page code that I used to render the PDFs from the images above:
And the sample HTML table:
Final remarks
The solution above requires you to pass the generated HTML back to the VF Page and render it unescaped. You should always be careful when doing this as it can result in XSS as reported by the PMD Code Analyzer.