Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A4 page like layout in html

Tags:

html

css

printing

I am working on small web based application where user is presented 2-3 page long report which can be printed as PDF. I looked at different solutions on stackoverflow / internet and found somewhat working solution to printing side (contents are printed with extra margins but i need to work on that to fix it) my current problem is i am not able to display html content in browser with page like layout. I am able to show 1st page with A4 size but as soon as content goes beyond 1 page it appears as if it printed outside page, you can check the images below

  1. How page is shown in Browser enter image description here

  2. How it's print preview look like enter image description here

Here is the CSS

.A4 {
   background: white;
   width: 21cm;
   height: 29.7cm;
   display: block;
   margin: 0 auto;
   padding: 10px 25px;
   margin-bottom: 0.5cm;
   box-shadow: 0 0 0.5cm rgba(0,0,0,0.5);
}

@media print {
.page-break { display: block; page-break-before: always; }
size: A4 portrait;
} 

@media print {
 .noprint {display:none;}
 .enable-print { display: block; }
}

I am trying to solve below problems,

  1. Would love if all the report is shown with page like layout (additionally, if i can show pages in horizontal pagination instead of long vertical page)
  2. No padding issues while printing, what you see is printed!
like image 827
Ninad Mhatre Avatar asked Sep 14 '16 08:09

Ninad Mhatre


People also ask

What is equivalent to A4?

The most common of these sheet sizes is the international letterhead size A4, which measures 8-1/4 x 11-3/4 in, or 210 x 297 mm. These paper measurements are defined by the ISO 216 standard.


2 Answers

Your 2nd problem:

You have to set the body margin and padding to zero. You also need to remove box shadow, margin, width and height from the A4 class in order to print multiple pages.

.A4 {
  background: white;
  width: 21cm;
  height: 29.7cm;
  display: block;
  margin: 0 auto;
  padding: 10px 25px;
  margin-bottom: 0.5cm;
  box-shadow: 0 0 0.5cm rgba(0, 0, 0, 0.5);
  overflow-y: scroll;
  box-sizing: border-box;
}

@media print {
  .page-break {
    display: block;
    page-break-before: always;
  }

  size: A4 portrait;
}

@media print {
  body {
    margin: 0;
    padding: 0;
  }

  .A4 {
    box-shadow: none;
    margin: 0;
    width: auto;
    height: auto;
  }

  .noprint {
    display: none;
  }

  .enable-print {
    display: block;
  }
}

Your first problem:

You could try to create a pagination feature by calculating the scrollheight, and keep removing elements from the pages untill the scollheight is smaller than the page itself.

Example: https://jsfiddle.net/tk8rwnav/31/

var max_pages = 100;
var page_count = 0;

function snipMe() {
  page_count++;
  if (page_count > max_pages) {
    return;
  }
  var long = $(this)[0].scrollHeight - Math.ceil($(this).innerHeight());
  var children = $(this).children().toArray();
  var removed = [];
  while (long > 0 && children.length > 0) {
    var child = children.pop();
    $(child).detach();
    removed.unshift(child);
    long = $(this)[0].scrollHeight - Math.ceil($(this).innerHeight());
  }
  if (removed.length > 0) {
    var a4 = $('<div class="A4"></div>');
    a4.append(removed);
    $(this).after(a4);
    snipMe.call(a4[0]);
  }
}

$(document).ready(function() {
  $('.A4').each(function() {
    snipMe.call(this);
  });
});

This example breaks on every element. The paragraphs don't break on words, but you can implement this, but that will get complicated very fast.

like image 153
Simon Backx Avatar answered Sep 21 '22 01:09

Simon Backx


Below is a revised version of the snipMe() function to ensure elements in Page 2-n are in the original order. I also added comments.

   function snipMe() {
      page_count++;
      if (page_count > max_pages) {
        return;
      }
      var long = $(this)[0].scrollHeight - Math.ceil($(this).innerHeight());
      var children = $(this).children().toArray(); // Save elements in this page to children[] array
      var removed = [];
      // Loop while this page is longer than an A4 page
      while (long > 0 && children.length > 0) {
        var child = children.pop(); // Remove last array element from the children[] array 
        $(child).detach();  // JQuery Method detach() removes the "child" element from DOM for the current page
        removed.push(child);  // Add element that was removed to the end of "removed" array
        long = $(this)[0].scrollHeight - Math.ceil($(this).innerHeight()); // Compute current size of the page 
      }
      // If elements were removed from the page 
      if (removed.length > 0) {
        var rev_removed = removed.reverse();  // Reverse the order of the removed array
        var a4 = $('<div class="A4"></div>'); // Start a new page
        a4.append(rev_removed); // Add elements removed from last page to the new page
        $(this).after(a4); // Add the new page to the document
        snipMe.call(a4[0]); // Recursively call myself to adjust the remainder of the pages
      }
    }
like image 25
Mike Meinz Avatar answered Sep 20 '22 01:09

Mike Meinz