Using CSS to style using mPDF

This follows on from my previous blog Producing a printed newsletter from a Drupal website.

I was creating a system in Drupal to allow a Church newsletter to be displayed on the website and to be printable. I was achieving this by using the module PDF using mPDF to output the newsletter in a consistent style cross browser for printing. This allows the use of CSS to style the PDF. Sounds great to someone use to CSS, however, there are only so many standards supported by mPDF and there is no Firebug to make life easier.

To start at the beginning. In order to allow me to style the web version and the PDF version differently, I activated the PDF view mode under "Custom display settings" in "Manage Display". This then allowed me to use the following within the node template file to separate the PDF mark-up:

<?php if($view_mode!="PDF"){ ?>
    <!--Web View Markup-->
<?php }else{ ?>
    <!--PDF View Markup-->
<?php } ?>

The mark-up needed to be separated because mPDF doesn't interpret all CSS correctly. I didn't need to use web standards as this view is ultimately only for printing, therefore, I could use non-standard HTML and inline CSS to help with layout. It takes a lot of trial and error, but I eventually got things working the way I wanted. Here are my top tips for styling with mPDF:

1. Use very specific CSS selectors.

Sometimes using the ID of an element doesn't seem to apply the styling to it, instead, try adding a container class as well. The slightly more specific selectors seemed to work more often.

2. Use inline styling if needed.

I found that some styles just wouldn't apply to the element no matter how I declared them. So the only other way to do it is with inline styling. Inline styling was pretty reliable for applying styles which I knew mPDF understood, but just wasn't applying in the correct place.

3. Use tables.

Yes, you can break the "no tables for layout" rule in this situation. It's only for printing so as long as it looks right.

4. Avoid floating elements or be clever if you have to use float.

It just doesn't work very well. Floating an element will only float next to a single block element which caused me a particular problem. I needed an image to float to the right of a section of text. The text needed to wrap around the image so the only way to do it was with a float. However, the section of text included paragraphs. This caused a problem as when a paragraph ended, the next would only start under the bottom of the floated image. So I had to come up with a work around.

Although I wanted the paragraphs for the web view, I only needed them to look like paragraphs for the printed version. Therefore, I wrote a bit of PHP to remove all opening <p> tags and to replace all closing </p> tags with two <br /> tags. I then placed the text and the image within a single <p> element. This made it still look like paragraphs, but as it was only one block, the image floated perfectly.

<?php 
    $newBody = str_replace("<p>", "", $content['body']['#items']['0']['value']);
    $newBody2 = str_replace("</p>", "<br/><br/>", $newBody);
    print $newBody2;
?>
5. Beware of borders on only one side.

I found borders unpredictable if you only wanted them on one side. It was just at the bottom of sections I was trying to use them to separate content, but they would quite often just not show. Therefore, I used a <div> element with a background colour and height set in CSS to give the same look.

It took a while, but I eventually got everything looking how I wanted it. Once it was all correct, mPDF worked perfectly to output a consistent newsletter for printing.

Comments

Hi, i have a problem styling my label element (which is inside div) using css. i wanted to use position:absolute, top:55px;left:323px to set the position of my element but mpdf only support position for block element. Somemore i tried to set italic,bold or underline my label element but none of them work. Any idea how i can do it? Please help me!

Sorry, only just noticed this comment. Hopefully you found a solution.

Make sure you have position:relative; set on the div. And add display:block; to both elements. If that doesn't do anything, then you might not be able to make it work.

I found in some situations CSS just won't do what you want in mpdf. So it might be a case where you have to find a way to change the HTML to work for you.