304

I have a HTML report, which needs to be printed landscape because of the many columns. It there a way to do this, without the user having to change the document settings?

And what are the options amongst browsers.

John
  • 29,788
  • 18
  • 89
  • 130
doekman
  • 18,750
  • 20
  • 65
  • 86

18 Answers18

473

In your CSS you can set the @page property as shown below.

@media print{@page {size: landscape}}

The @page is part of CSS 2.1 specification however this size is not as highlighted by the answer to the question Is @Page { size:landscape} obsolete?:

CSS 2.1 no longer specifies the size attribute. The current working draft for CSS3 Paged Media module does specify it (but this is not standard or accepted).

As stated the size option comes from the CSS 3 Draft Specification. In theory it can be set to both a page size and orientation although in my sample the size is omitted.

The support is very mixed with a bug report begin filed in firefox, most browsers do not support it.

It may seem to work in IE7 but this is because IE7 will remember the users last selection of landscape or portrait in print preview (only the browser is re-started).

This article does have some suggested work arounds using JavaScript or ActiveX that send keys to the users browser although it they are not ideal and rely on changing the browsers security settings.

Alternately you could rotate the content rather than the page orientation. This can be done by creating a style and applying it to the body that includes these two lines but this also has draw backs creating many alignment and layout issues.

<style type="text/css" media="print">
    .page
    {
     -webkit-transform: rotate(-90deg); 
     -moz-transform:rotate(-90deg);
     filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
    }
</style>

The final alternative I have found is to create a landscape version in a PDF. You can point to so when the user selects print it prints the PDF. However I could not get this to auto print work in IE7.

<link media="print" rel="Alternate" href="print.pdf">

In conclusion in some browsers it is relativity easy using the @page size option however in many browsers there is no sure way and it would depend on your content and environment. This maybe why Google Documents creates a PDF when print is selected and then allows the user to open and print that.

KęstutisV
  • 61
  • 1
  • 7
John
  • 29,788
  • 18
  • 89
  • 130
  • 37
    odd that it says 'size' can be landscape, when that's actually an 'orientation'. – Magnus Smith Nov 10 '09 at 16:20
  • 1
    `@page size` Does not seem to work on all modern browsers, only Firefox. Chrome and Opera both disregard this as far as I have seen. – Justin808 May 17 '11 at 22:43
  • I have updated the answer after doing some more research, thanks – John May 18 '11 at 07:42
  • 2
    `size: landscape` is **NOT** part of CSS2.1, although `@page` rules are. It is, however, part of CSS3. For confirmation, try using the [W3C CSS Validator](http://jigsaw.w3.org/css-validator/#validate_by_input+with_options) and enter `@page {size: landscape}` and compare results with "Profile" set to level 2.1 vs level 3. – daiscog Nov 02 '11 at 10:56
  • @Magnus Smith - The spec says it can be set to size:A4 landscape but the paper can be omitted. – John Nov 25 '11 at 12:21
  • +1 for the very detailed answer with multiple solutions! It is sad that as of September 2012 modern browsers still don't support the landscape orientation. (tested in Chrome and Firefox both current versions as of this post) – L84 Sep 20 '12 at 19:06
  • 1
    When you have a div that occupy 100 width or height of the page, the rotation do not make the div occupy the space of a portrait page, but a lanscape one rotated. So some parts of the div are then out of the page. – Oliver Jan 12 '14 at 02:28
  • Note that rotating the contents has the (probably) unwanted side effect that when the user sets the paper orientation in the printer settings to be landscape it prints portrait and vice versa. – JJJ Jun 28 '14 at 08:47
  • Hello John, some of the commenter says it works in Firefox and some says it doesn't work in Firefox. So I want to know whether @page properties reflect in print preview (Yes I've specified inside `@media print { @page...`)? If Yes then I'm not getting A3 Landscape orientation in Firefox v43, Ubuntu 14.04. – learner Jun 30 '16 at 14:30
  • Works for Chrome version 49. – Pavlos Papanikolaou Jul 04 '16 at 16:13
  • 8
    @AbeerSul - To be honest, regarding CSS, what _does_ work in IE ;) – Tony Mar 29 '17 at 22:06
  • Here is a simple solution which work in the most browsers http://stackoverflow.com/a/44069821/632199 – Denis May 19 '17 at 12:24
  • I've tried the link with media=print and rel=alternate from a PDF suggestion but when pressing print it still tries to print the html. Any suggestions what I might be doing wrong? I've tried in Safari and Chrome. Thanks. – jsaven Nov 28 '20 at 02:52
42

My solution:

<style type="text/css" media="print">
    @page { 
        size: landscape;
    }
    body { 
        writing-mode: tb-rl;
    }
</style>
  • With media="print" will apply only on Print.
  • This works in IE, Firefox and Chrome
Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
22

The size property is what you're after as mentioned. To set both the the orientation and size of your page when printing, you could use the following:

/* ISO Paper Size */
@page {
  size: A4 landscape;
}

/* Size in mm */    
@page {
  size: 100mm 200mm landscape;
}

/* Size in inches */    
@page {
  size: 4in 6in landscape;
}

Here's a link to the @page documentation.

robstarbuck
  • 6,893
  • 2
  • 41
  • 40
  • When used with bootstrap, this declaration has to be stored into a separate `.css` file or else if it's inline, the default boostrap declaration (`size: a3`) will take precedence. – caram Dec 19 '19 at 15:51
18

It's not enough just to rotate the page content. Here is a right CSS which work in the most browsers (Chrome, Firefox, IE9+).

First set body margin to 0, because otherwise page margins will be larger than those you set in the print dialog. Also set background color to visualize pages.

body {
  margin: 0;
  background: #CCCCCC;
}

margin, border and background are required to visualize pages.

padding must be set to the required print margin. In the print dialog you must set the same margins (10mm in this example).

div.portrait, div.landscape {
  margin: 10px auto;
  padding: 10mm;
  border: solid 1px black;
  overflow: hidden;
  page-break-after: always;
  background: white;
}

The size of A4 page is 210mm x 297mm. You need to subtract print margins from the size. And set the size of page's content:

div.portrait {
  width: 190mm;
  height: 276mm;
}
div.landscape {
  width: 276mm;
  height: 190mm;
}

I use 276mm instead of 277mm, because different browsers scale pages a little bit differently. So some of them will print 277mm-height content on two pages. The second page will be empty. It's more safe to use 276mm.

We don't need any margin, border, padding, background on the printed page, so remove them:

@media print {
  body {
    background: none;
    -ms-zoom: 1.665;
  }
  div.portrait, div.landscape {
    margin: 0;
    padding: 0;
    border: none;
    background: none;
  }
  div.landscape {
    transform: rotate(270deg) translate(-276mm, 0);
    transform-origin: 0 0;
  }
}

Note that the origin of transformation is 0 0! Also the content of landscape pages must be moved 276mm down!

Also if you have a mix of portrait and lanscape pages IE will zoom out the pages. We fix it by setting -ms-zoom to 1.665. If you'll set it to 1.6666 or something like this the right border of the page content may be cropped sometimes.

If you need IE8- or other old browsers support you can use -webkit-transform, -moz-transform, filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3). But for modern enough browsers it's not required.

Here is a test page:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style>
      ...Copy all styles here...
    </style>
  </head>
  <body>
    <div class="portrait">A portrait page</div>
    <div class="landscape">A landscape page</div>
  </body>
</html>
Denis
  • 1,167
  • 1
  • 10
  • 30
  • Thank you so much, works like a charm (used chrome) with the web pages that consist of a mixture of both landscape and portrait modes. – zcahfg2 Jun 27 '19 at 01:17
  • Where are div.portrait, div.landscape from? – zcahfg2 Jun 27 '19 at 01:37
  • Did this work in IE 11 for anyone? Seems all the elements are off allingned. – mzonerz Sep 25 '19 at 11:31
  • 1
    @mzonerz I've just tested in IE 11, it works fine. I added a testing html at the end of the answer. Please note that you should set page margings to 10mm in the printing settings. If you need a different page margins, then you have to update the following values: padding: 10mm; width: 190mm; height: 190mm; – Denis Sep 25 '19 at 12:20
  • @Denis Thank you for your efforts.. Actually this is the only solution worked for me so far..nice!!, People who integrate this solution in sharepoint Intranet sites may need to turn off the Compatibility View Settings. – mzonerz Sep 26 '19 at 09:37
  • I'm printing to PDF in lanscape, I had to set the "MS Print to PDF" printer to `Landscape` and swap the `width` and `height` for `div.portrait` and `div.landscape`. Works great otherwise! – caram Nov 28 '19 at 15:20
  • 1
    landscape mechanism https://codepen.io/04/full/mdBZqvM – 井上智文 Jan 21 '22 at 07:40
14

Try to add this your CSS:

@page {
  size: landscape;
}
scunliffe
  • 62,582
  • 25
  • 126
  • 161
gizmo
  • 11,819
  • 6
  • 44
  • 61
  • 3
    Did this work for you with any of the browsers? With IE8 and Firefox3.5 it didn't seem to make any difference to the print preview. – Daniel Ballinger Jul 28 '09 at 03:15
  • The print preview does not follow all the CSS properties, unfortunately. But this should works in all the current browsers. – gizmo Jul 28 '09 at 05:30
  • Thanks for following up on this. It doesn't seem to work for me with actual printing either. Have I missed something? My test file is as follows: (I've had to truncate the paragraph content to fit in the comment box) Landscape testing Page

    Lorem ipsum dolor sit amet, ...

    – Daniel Ballinger Jul 28 '09 at 23:06
  • I've tried every combination of the @Page rule shown on this page and some from other sites, as well as the example in O'Reilly's HTML/XHTML: The Definitive Guide, Fifth Edition. I haven't been able to get this to work in IE8, Firefox 3.6, or Chrome 7.0. – Paul Keister Nov 22 '10 at 19:20
  • I know its 2012...but this answer helped me...to support the landscape option for IE8...thanks – Vikram Jul 24 '12 at 19:54
  • In 2022, this worked great in Chrome and Microsoft Edge. Just add it to its own StyleSheet and add to the head of any pages that need to print (tables, etc.) in Landscape. – FlashTrev Jul 26 '22 at 08:58
13

Quoted from CSS-Discuss Wiki

The @page rule has been cut down in scope from CSS2 to CSS2.1. The full CSS2 @page rule was reportedly implemented only in Opera (and buggily even then). My own testing shows that IE and Firefox don't support @page at all. According to the now-obsolescent CSS2 spec section 13.2.2 it is possible to override the user's setting of orientation and (for example) force printing in Landscape but the relevant "size" property has been dropped from CSS2.1, consistent with the fact that no current browser supports it. It has been reinstated in the CSS3 Paged Media module but note that this is only a Working Draft (as at July 2009).

Conclusion: forget about @page for the present. If you feel your document needs to be printed in Landscape orientation, ask yourself if you can instead make your design more fluid. If you really can't (perhaps because the document contains data tables with many columns, for example), you will need to advise the user to set the orientation to Landscape and perhaps outline how to do it in the most common browsers. Of course, some browsers have a print fit-to-width (shrink-to-fit) feature (e.g. Opera, Firefox, IE7) but it's inadvisable to rely on users having this facility or having it switched on.

Community
  • 1
  • 1
Ahmad Alfy
  • 13,107
  • 6
  • 65
  • 99
8

You might be able to use the CSS 2 @page rule which allows you to set the 'size' property to landscape.

Ian Oxley
  • 10,916
  • 6
  • 42
  • 49
5

You can also use the non-standard IE-only css attribute writing-mode

div.page    { 
   writing-mode: tb-rl;
}
yann.kmm
  • 827
  • 7
  • 21
  • 1
    This does reorient the page content but doesn't really change the page layout to landscape. I.e. the headers and footers will still be added as if the page was portrait. – Daniel Ballinger Jul 28 '09 at 03:13
4

I tried Denis's answer and hit some problems (portrait pages didn't print properly after going after landscape pages), so here is my solution:

body {
  margin: 0;
  background: #CCCCCC;
}

div.page {
  margin: 10px auto;
  border: solid 1px black;
  display: block;
  page-break-after: always;
  width: 209mm;
  height: 296mm;
  overflow: hidden;
  background: white;
}

div.landscape-parent {
  width: 296mm;
  height: 209mm;
}

div.landscape {
  width: 296mm;
  height: 209mm;
}

div.content {
  padding: 10mm;
}

body,
div,
td {
  font-size: 13px;
  font-family: Verdana;
}

@media print {
  body {
    background: none;
  }
  div.page {
    width: 209mm;
    height: 296mm;
  }
  div.landscape {
    transform: rotate(270deg) translate(-296mm, 0);
    transform-origin: 0 0;
  }
  div.portrait,
  div.landscape,
  div.page {
    margin: 0;
    padding: 0;
    border: none;
    background: none;
  }
}
<div class="page">
  <div class="content">
    First page in Portrait mode
  </div>
</div>
<div class="page landscape-parent">
  <div class="landscape">
    <div class="content">
      Second page in Landscape mode (correctly shows horizontally in browser and prints rotated in printer)
    </div>
  </div>
</div>
<div class="page">
  <div class="content">
    Third page in Portrait mode
  </div>
</div>
Arkadiy Bolotov
  • 314
  • 2
  • 8
3

I created a blank MS Document with Landscape setting and then opened it in notepad. Copied and pasted the following to my html page

<style type="text/css" media="print">
   @page Section1
    {size:11 8.5in;
    margin:.5in 13.6pt 0in 13.6pt;
    mso-header-margin:.5in;
    mso-footer-margin:.5in;
    mso-paper-source:4;}
div.Section1
    {page:Section1;}
</style>



<div class="Section1"> put  text / images / other stuff  </div>

The print preview shows the pages in a landscape size. This seems to be working fine on IE and Chrome, not tested on FF.

Shankar
  • 125
  • 2
  • 12
2

This also worked for me:

@media print and (orientation:landscape) { … }
Navin Rauniyar
  • 10,127
  • 14
  • 45
  • 68
2

Here's what I came up with - add a negative rotation to the <html> element and a positive rotation of equal abs value to the <body>. That saved having to add a ton of CSS to style the body, and it worked like a charm:

html { 
  transform: rotate(-90deg);
}

body { 
  transform: rotate(90deg);
}
Rich
  • 3,156
  • 3
  • 19
  • 29
1
-webkit-transform: rotate(-90deg); -moz-transform:rotate(-90deg);
     filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);

not working in Firefox 16.0.2 but it is working in Chrome

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Satheesh
  • 19
  • 1
1

I tried to solve this problem once, but all my research led me towards ActiveX controls/plug-ins. There is no trick that the browsers (3 years ago anyway) permitted to change any print settings (number of copies, paper size).

I put my efforts into warning the user carefully that they needed to select "landscape" when the browsers print dialog appeared. I also created a "print preview" page, which worked much better than IE6's did! Our application had very wide tables of data in some reports, and the print preview made it clear to the users when the table would spill off the right-edge of the paper (since IE6 couldnt cope with printing on 2 sheets either).

And yes, people are still using IE6 even now.

Magnus Smith
  • 5,895
  • 7
  • 43
  • 64
1
<style type="text/css" media="print">
.landscape { 
    width: 100%; 
    height: 100%; 
    margin: 0% 0% 0% 0%; filter: progid:DXImageTransform.Microsoft.BasicImage(Rotation=1); 
} 
</style>

If you want this style to be applied to a table then create one div tag with this style class and add the table tag within this div tag and close the div tag at the end.

This table will only print in landscape and all other pages will print in portrait mode only. But the problem is if the table size is more than the page width then we may loose some of the rows and sometimes headers also are missed. Be careful.

Have a good day.

Thank you, Naveen Mettapally.

DarthJDG
  • 16,511
  • 11
  • 49
  • 56
  • 1
    This rotates the contents of the screen by 90 degrees but the printout still comes out in protrait format. The worst of both worlds really, at least in ie8. – arame3333 Feb 09 '12 at 08:49
1

The problem I faced is probably the same you have. Everyone here is using CSS to provide it statically, but I had to look for a dynamic solution so that it would change based on the active element without reloading the page..

I created 2 files, portrait.css and landscape.css.

portrait.css is blank, but landscape.css has one line.

@media print{@page {size: landscape}}

in my primary file, I added this line of html to specify portrait.css as default.

 <link rel="stylesheet" id="PRINTLAYOUT" href="portrait.css" type="text/css" /></link>

Now, to switch you only have to change href in the element to switch printing modes.

$("#PRINTLAYOUT").attr("href","landscape.css")
  // OR 
document.getElementById("PRINTLAYOUT").href = "landscape.css" // I think...

This worked great for me, and I hope it helps someone else doing things the hard way like me.. As a note, $ represents JQuery.. If you are not using this yet, I highly recommend you start now.

thphoenix
  • 181
  • 4
1

If you are using React and libraries like MUI, using plain CSS in your React app is not a good practice. The better approach will be to use a style component called GlobalStyles, which we can import from Material UI. The code will look like this,

import { GlobalStyles } from '@mui/material';
const printStyle = {
  ['@media print']: {
    ['@page']: {
      size: 'landscape',
      margin: '2px',
     },
   },
 };

You might not need to use @page inside the @media print because @page is only for printing. Documentation

The margin will eliminate the URLs, the browser generates while printing.

We can use the GlobalStyles in our App container. Like this

const App: React.FC = () => (
  <>
     <GlobalStyles styles={printStyle} />
     <AppView />
  </>
 );

It will apply the above CSS whenever we call windows.print(). If you are using other libraries besides MUI, there should be some components or plugins that you can use to apply the CSS globally.

prajun7
  • 133
  • 11
-3

You can try the following:

@page {
    size: auto
}
geisterfurz007
  • 5,292
  • 5
  • 33
  • 54
sherz
  • 11
  • 3