Home > Net >  Wkhtmltopdf row alignment off converting HTML table
Wkhtmltopdf row alignment off converting HTML table

Time:01-17

Using wkhtmltopdf to convert an html table report:

<!DOCTYPE html>
<html lang="en"></html>
<head>
  <style type="text/css">
    @font-face {
      font-family: Plex;
      src: url(/home/shawn/Development/Websites/MDSova/restapi/templates/fonts/IBMPlexSans-Regular.ttf);
    }

    @font-face {
      font-family: Plex-Bold;
      src: url(/home/shawn/Development/Websites/MDSova/restapi/templates/fonts/IBMPlexSans-SemiBold.ttf);
    }

    body {
      font-family: Plex, Arial, Helvetica, sans-serif;
      background-color: #FFF;
      font-size: 18px;
    }

    h1,
    h2,
    h3 {
      margin: 0;
      padding: 0;
    }

    .report-data-table,
    .report-title-table {
      width: 100%;
      border-collapse: collapse;
    }

    .report-title-table {
      line-height: 36px;
    }

    .report-title-left,
    .title-right {
      width: 15%;
    }

    .report-title-center {
      width: 70%;
      text-align: center;
    }

    .report-title-right {
      text-align: right;
    }

    .report-date-header,
    .report-date-col {
      width: 10%;
      background-color: chocolate;
    }

    .report-for-header,
    .report-for-col {
      width: 14%;
      background-color: palegreen
    }

    .test {
      width: 78%;
      background-color: forestgreen;
    }

    .report-date-header,
    .report-for-header,
    .report-source-header,
    .report-sourcename-header,
    .report-account-header,
    .report-method-header,
    .report-reference-header,
    .report-amount-header {
      font-family: Plex-Bold;
      border-bottom: 1px solid #333;
    }
  </style>
</head>
<body>
  <table >
    <tr>
      <td >01/15/2023</td>
      <td >
        <h1>Payment Ledger</h1>
      </td>
      <td >11:23AM</td>
    </tr>
  </table>
  <table >
    <tr>
      <td >Payment Date</td>
      <td >Payment For</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
  </table>
</body>

enter image description here

I understand there is a lot of code here, but the misalignment is several rows down. it isn't on just one row either - it's random. Shows fine when the html is thrown in a browser but it doesn't translate to the printed version. What can I do to get this corrected?? Thanks

CodePudding user response:

I could reproduce the problem after adding several more rows, showing that the issue is indeed rather unpredictable.

However, the issue seems to be caused by the border-collapse: collapse; css property. Removing this made all rows have the same height.

Of course this also causes white borders to appear around every table cell, which is probably not desired.

To make the borders blend in with the cells a solution is to color the columns using a background pattern for the whole table, instead of a background-color property for individual cells.

In the code below I created an inline svg image that consists of three rectangles with the widths and colors of the table columns:

<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100'>
   <rect width='15%' height='100' fill='chocolate'/>
   <rect x='15%' width='25%' height='100' fill='palegreen'/>
   <rect x='40%' width='60%' height='100' fill='forestgreen'/>
</svg>

For the column widths to be calculated properly during the conversion I needed to adjust the dpi setting to 130:

wkhtmltopdf --dpi 130 input.html output.pdf

HTML code:

<!DOCTYPE html>
<html lang="en"></html>
<head>
  <style type="text/css">
    body {
      font-family: Plex, Arial, Helvetica, sans-serif;
      background-color: #FFF;
      font-size: 18px;
    }

    h1,
    h2,
    h3 {
      margin: 0;
      padding: 0;
    }
    .report-data-table,
    .report-title-table {
      width: 100%;
    }

    .report-title-table {
      line-height: 36px;
    }

    .report-title-left,
    .title-right {
      width: 15%;
    }

    .report-title-center {
      width: 70%;
      text-align: center;
    }

    .report-title-right {
      text-align: right;
    }

    .report-date-header,
    .report-date-col {
      width: 15%;
    }

    .report-for-header,
    .report-for-col {
      width: 25%;
    }

    .test {
      width: 60%;
    }
    .svgbackground {
        background-image: url("data:image/svg xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100'><rect width='15%' height='100' fill='chocolate'/><rect x='15%' width='25%' height='100' fill='palegreen'/><rect x='40%' width='60%' height='100' fill='forestgreen'/></svg>");
        }
  </style>
</head>
<body>
  <table >
    <tr>
      <td >01/15/2023</td>
      <td >
        <h1>Payment Ledger</h1>
      </td>
      <td >11:23AM</td>
    </tr>
  </table>
  <div class=svgbackground>
  <table >
    <tr>
      <td >Payment Date</td>
      <td >Payment For</td>
      <td ></td>
    </tr>
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
    <!-- ... many more rows here -->
    <tr >
      <td >01/23/2023</td>
      <td >PAYMENT ON ACCOUNT</td>
      <td ></td>
    </tr>
  </table>
  </div>
</body>

Resulting pdf:

enter image description here

  • Related