Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set Safari print margins via CSS to print borderless

I want to print a webpage to PDF without any margins in Safari. Page size is set to 'A4 borderless' in the print dialogue.

Whatever I seem to do, Safari on OSX is adding an extra margin around my HTML. Check 'print backgrounds' to see what I mean.

Clearly the @page-rule has no effect for Safari, but are there any other ways?

http://jsfiddle.net/willemvb/psFHC/

@page {
  size: 21cm 29.7cm;   /*A4*/
  margin: 0; /*webkit says no*/
}

html{
    margin: 0;
    padding: 0;
    width: 100%;
}

body {
    margin: 0;
    padding: 0;
    font-family: sans-serif;
    width: 100%; 
    background: #eee;
}

like image 920
Willem Van Bockstal Avatar asked Oct 31 '12 08:10

Willem Van Bockstal


2 Answers

There is 3 things to take in consideration:

  1. The margin of the page's rule, unfortunately

    @page {
    margin: 0cm !important;
    }
    

    Has no effect on Safari 6, where it does in Chrome 23. As I know, as long as Safari is not supporting this, there is no solution (it seems to be fixed to around 10mm).

  2. The page setting as seen here you might have to define a custom "Paper Size" in the "Print…" menu panel without any margin (you did it already btw).

  3. Obviously to take care of the other inner content html, body… not to have any margin.

like image 134
Flavien Volken Avatar answered Sep 29 '22 10:09

Flavien Volken


The selected answer isn't quite right. To correctly answer the question you need to understand the problem first.

Borderless printing and printers:

Very few printers can "actually" print borderless prints even if they say they do. Most just enlarge the print a bit so it stretches beyond the actual page and, usually, give you a slider to adjust that amount. The reason is that most printer don't have a sensor to determine where the paper actually is, it presumes paper is there and for most prints it doesn't matter if it's 0,5mm off or even 1mm.

For borderless it matters because the print comes out with a white (paper) border around it.

For this reason 95% of printers out there mimic this "borderless" print by actually running ink into thin air for a little bit just so the paper is covered all the way to the edge. Printing into thin air is bad, can cause smudges in the long term and should be avoided, so the amount of printing over the edge must be adjusted to a minimum.

Good large format printers have a sensor to detect paper width but it's used to adjust the paper slightly because the length, 50 to 150m per roll, can cause even a 0,1mm misalignment to become a problem and cause paper jams.

To fix this problem entirely, "bleed" is used, where you actually design everything to a slightly larger paper which is cut to size afterwards.

Ok... now you know.

Onwards to the problem of CSS borderless prints:

To fully understand this problem one must be acquainted with the "Box".

Box Model

The Box models the behaviour of almost every element in CSS. The page you want to print is usually wrapped in a tag of some sort, either a div with and id or a class like this:

<div class="page">lots of content</div>

We will be talking about the black line, called the border, and it's two siblings "margin" and "padding".

Unbeknownst to most is the fact that every printer out there actually reports the margins within it can print for every paper size it supports.

Here is an HP 2800dtn doing so (just hover over the paper size for a while and it will appear).

HP 2800dtn

The "fix":

Safari is doing the right thing. There I said it... it's not a bug.

The reason it apparently refuses to produce borderless prints is that it's actually not possible (in the real world). You can do it, but people printing it at 100% zoom will have the content trimmed off by the printer, which, as I've described, can't print to the edge.

So most will have to "fit to paper" margins (the default OS X behaviour, minified to around 98% zoom) then enable borderless mode on the printer which in turn magnifies the minified 98% zoom version to 103%. If you do the math you get a weird number of probably 101.5% of the original version (I can't say for sure, I'm not very good at math if it isn't divided by two :) This isn't exactly a problem for fonts and vector graphics, but it wreaks havoc in the pixel world. The pixel world likes, just like I do, the number 2 by default, the rest is just "smoothing" it over.

So you can't fix it, because it isn't broken. Safari puts the border of the div and all its inner elements inside the "printable area" of the paper as reported by the printer. Good!

The solution:

You can't know the printer margins until you command+p and select a paper size.

But what can you do in CSS to get that "what you see is what you get" feeling everyone likes?

  1. Use the margin on the div.page you defined. Note that margin is calculated form the the element containing that div. So you need to wrap the page in the actualpage

Define CSS per media type so that the screen shows imaginary print margins (close to the real thing) and the print get's a version without margins.

/* @media all { */ /* I like using these */
  div.actualpage {
   ...
   height: 210mm; /* DIN A4 standard paper size */
   width: 297mm;
   ...
  }
  div.page {
   ...
   /* margin: 0;  you don't really have to explicitly set it to 0 unless it's already set to something else */
   ...
  }
/* } */

@media screen {
 div.page {
  ...
  margin: 5mm 5mm 5mm 10mm; /* printers usually have a bigger bottom margin*/
  ...
  }
}

@media print {
 div.page {
  ...
  margin: 0mm; /* Browser will apply the correct margins when it prints */
  ...
  }
}

If you can't wrap the page into another div you can hack it (ie: less elegant solution) with padding.

/* @media all { */ /* I like using these */
  div.page {
   ...
   height: 210mm; /* DIN A4 standard paper size */
   width: 297mm;
   /* padding: 0;  you don't really have to explicitly set it to 0 unless it's already set to something else */
   ...
  }
/* } */

@media screen {
 div.page {
  ...
  padding: 5mm 5mm 5mm 10mm; /* printers usually have a bigger bottom margin*/
  ...
  }
}

@media print {
 div.page {
  ...
  padding: 0mm; /* Browser will apply the correct margins when it prints */
  ...
  }
}
like image 36
unom Avatar answered Sep 29 '22 09:09

unom