I am using wkhtmltopdf to convert part of a HTML page to a PDF document that may be several pages long (depending on the text the user inputs to be converted).
The wkhtmltopdf is working correctly. I am now wanting to indicate to the user where the page breaks will occur before the user creates their PDF document.
How do I overlay a HTML div tag to replicate a hr tag (< hr />
) on top of the HTML text that is to be converted to the PDF document to indicate where the page breaks are most likely to occur before the contents of the form is converted to the PDF document?
I am thinking that there will have to be a JQuery / JavaScript loop condition to overlay the HTML div tag (indicating the page break) each 5cms (for the purpose of this post, assume that the page break will occur on the PDF each 5cms).
I have tried several times to do this myself, but I cannot get the jq/js code right (and it is killing me).
Here is a fiddle of the code below without the js/jq.
Here is the HTML:
<body>
<div id="main_area">
<div id="text">
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
<p>
Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
</p>
</div>
<div id='page_break'></div>
</div>
</body>
Here is the CSS:
If I add the following no-print CSS to the HTML div tag (indicating the page break), the div tag will not be printed/converted to the PDF document by wkhtmltopdf, in case you are wondering how the page break tag will be handled in the PDF document.
@media print {
/* prevents the element from being printed in the pdf */
.no_print, .no_print * {
display: none !important
}
}
#main_area {
padding: 2px;
width:100%;
background:#fff;
color:#333;
}
#text {
z-index:1;
}
#page_break {
position: absolute;
width: 100%;
height: 5px;
background: red;
top: 5cm;
z-index:0;
opacity: 0.2;
}
Fiddle
The simplest way to do this, is by stacking transparent <div>
s that have a height of the desired distance and a visible bottom border. We can repurpose the div#page_break
in the original HTML to contain these <div>
s. There is no need to use z-index
, because positioned elements are always layered on top of unpositioned elements. So we can start by changing the CSS into this:
#main_area {
padding: 2px;
width: 100%;
background: #fff;
color: #333;
}
#page_break {
position: absolute;
top: 0;
width: 100%;
opacity: 0.2;
}
#page_break > div {
width: 100%;
height: 5cm;
border-bottom: 5px solid red;
margin-bottom: -5px;
/* negative margin above ensures that the distance
between two rulers is exactly the height of the div
*/
}
If we now consider the relevant bit of the original HTML,
<div id="main_area">
<div id="text">
...
</div>
<div id='page_break'></div>
</div>
we won't see any rulers yet, because we added the ruler container but we didn't give it any <div>
s to contain yet. For every child <div>
that we add, we will obtain a new ruler, where the first is positioned 5cm from the top of the #main_area
and each next ruler is positioned 5cm below the previous:
<div id="main_area">
<div id="text">
...
</div>
<div id='page_break'>
<div></div> <!-- first ruler, 5cm from top -->
<div></div> <!-- second ruler, 10cm from top -->
<div></div> <!-- third ruler, 15cm from top -->
</div>
</div>
In order to append a new <div>
to another element in jQuery, we can use .appendTo
:
$('<div>').appendTo('#page_break');
If necessary, we can insert another method call in order to adjust properties of the new <div>
, such as .height
:
$('<div>').height(400).appendTo('#page_break'); // 400 pixels
Now we just have to repeat this often enough to place exactly enough rulers. .height
happens to be our friend again:
var textHeight = $('#text').height();
This is a height in pixels. Fortunately, according to the CSS standard there is a fixed number of pixels in a centimeter (even in print), so we can just do some calculations:
var pixelsPerInch = 96;
var cmPerInch = 2.54;
var pixelsPerCm = pixelsPerInch / cmPerInch;
pixelsPerCm
is about 37.8. @pottedmeat7's variable onePixel
is the inverse of this, i.e., the number of centimeters per pixel. 5cm happens to be about 189px.
We now know enough to roll a loop that adds <div>
s to the #page_break
until the height of the #text
has been filled. The simplest case, where all distances are fixed to 5cm, just requires us to divide the height of the #text
by 5cm:
var divisions = Math.floor((textHeight / pixelsPerCm) / 5);
var breaks = $('#page_break');
for (var i = 0; i < divisions; ++i) {
$('<div>').appendTo(breaks);
}
We floor the divisions
, because otherwise you'll get a dangling ruler below the text whenever the textHeight
is not an exact multiple of 5cm. breaks
is an optimization so jQuery doesn't have to look up the #page_break
selector on every iteration of the loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With