Search code examples
phphtmldompdf

DomPDF Calculate height of each div to prevent multiple pages


I am currently creating a resume exporting tool using domPDF. I have a DB that contains all the resume data (title, description). With a loop, I am building my PDF resume which looks like this :

resume

This is the code for the left column of my resume :

$q_cv_categories = $bdd->query('SELECT * FROM cv_category WHERE cv_column = "left"');
$q_cv_categories->execute();

while($cv_categories = $q_cv_categories->fetch()){

  $html .= '<div class="special-heading-pdf">';
  $html .= '<h3>'.constant($cv_categories['category_name']).'</h3>';
  $html .= '</div>';

  $q_cv_data = $bdd->prepare('SELECT * FROM cv_data WHERE category_id = :category ORDER BY importance DESC LIMIT 5');
  $q_cv_data->bindValue('category', $cv_categories['id'], PDO::PARAM_INT);
  $q_cv_data->execute();
  while($cv_data = $q_cv_data->fetch()){

    $html .= '<div class="resume-information"><h4 class="title-resume-data">'.constant($cv_data['title']).'</h4>';
    $html .= '<p class="description-resume-data">'.constant($cv_data['description']).'</p></div>';

  }
  $q_cv_data->closeCursor();
}
$q_cv_categories->closeCursor();

I would like to be able to calculate the render height of each div with the resume-information class, so I can display 4 instead of 5 computer science achievements (or even 3 if needed) in order to keep the resume one page only.

Thanks


Solution

  • I came up with the idea of calculating the exact height of each element in the resume. For example a line of descriptive text has a height of 17px in my PDF (A4, height of 1122px).

    For the right column of the resume, a line of text has a mean of 78 characters. By doing a strlen() of the description, I can approximate quite precisely the number of lines it will be taking.

    Here is the example of the script I used to calculate the height of the right column :

    $q_cv_categories = $bdd->query('SELECT * FROM cv_category WHERE cv_column = "right"');
    $q_cv_categories->execute();
    
    while($cv_categories = $q_cv_categories->fetch()){
    
      $right_height += CFG_RESUME_PDF_CSS_MARGIN_TOP_HEADING; // margin-top of heading computer achievement, work exp, etc.
      $right_height += CFG_RESUME_PDF_LINE_HEIGHT_PX*GetResumeLineCount(constant($cv_categories['category_name']), "right", "heading"); // heading
      $right_height += CFG_RESUME_PDF_CSS_PADDING_HEADING_BLUELINE+CFG_RESUME_PDF_CSS_HEADING_GREYLINE+CFG_RESUME_PDF_CSS_HEADING_BLUELINE; // blue line of heading
      $right_height += CFG_RESUME_PDF_CSS_MARGIN_BOTTOM_HEADING; // margin-bottom of heading
    
      $q_cv_data = $bdd->prepare('SELECT * FROM cv_data WHERE category_id = :category ORDER BY importance DESC LIMIT 5');
      $q_cv_data->bindValue('category', $cv_categories['id'], PDO::PARAM_INT);
      $q_cv_data->execute();
      while($cv_data = $q_cv_data->fetch()){
    
          $right_height += CFG_RESUME_PDF_LINE_HEIGHT_PX*GetResumeLineCount(constant($cv_data['title']), "right", "title");
          $right_height += CFG_RESUME_PDF_LINE_HEIGHT_PX*GetResumeLineCount(constant($cv_data['description']), "right", "description");
          $right_height += CFG_RESUME_PDF_CSS_MARGIN_BOTTOM_RESUME_INFORMATION; // margin-bottom of resume-information
    
      }
      $q_cv_data->closeCursor();
    }
    $q_cv_categories->closeCursor();
    

    The last step is to display for example 4 instead of 5 computer science achievements if the total height is more than 1100px (with a margin left of 22px), then calculate the total height once more, etc.