414

Whats the best way to print the contents of a DIV?

Bill Paetzke
  • 13,332
  • 6
  • 44
  • 46
usertest
  • 27,132
  • 30
  • 72
  • 94

31 Answers31

625

Slight changes over earlier version - tested on CHROME

function PrintElem(elem)
{
    var mywindow = window.open('', 'PRINT', 'height=400,width=600');

    mywindow.document.write('<html><head><title>' + document.title  + '</title>');
    mywindow.document.write('</head><body >');
    mywindow.document.write('<h1>' + document.title  + '</h1>');
    mywindow.document.write(document.getElementById(elem).innerHTML);
    mywindow.document.write('</body></html>');

    mywindow.document.close(); // necessary for IE >= 10
    mywindow.focus(); // necessary for IE >= 10*/

    mywindow.print();
    mywindow.close();

    return true;
}
dotancohen
  • 30,064
  • 36
  • 138
  • 197
Bill Paetzke
  • 13,332
  • 6
  • 44
  • 46
  • 12
    This is a quick solution. The ideal solution is to use a separate CSS for printing. Perhaps you can elaborate on the details (requirements) of your problem. – Bill Paetzke Feb 12 '10 at 22:18
  • Hi, thanks. I've got a separate css file called main.css but with no way of linking it to the new window. – usertest Feb 12 '10 at 22:25
  • 11
    You can reference the stylesheet in the popup window. Add another line of code in between tags: mywindow.document.write(''); – Bill Paetzke Feb 12 '10 at 22:32
  • I added the line of code to my example (commented out though), in case that wasn't clear. – Bill Paetzke Feb 12 '10 at 22:39
  • I couldn't get the stylesheet working, but I added them manually. Thanks. – usertest Feb 13 '10 at 22:38
  • To get all style sheets, you could add a line like this: mywindow.document.write($("HEAD").html()); Worked for me. Or just target the Style tags like this mywindow.document.write($("STYLE").html()); – Shane May 11 '11 at 20:39
  • If you're using IE, this post is helpful: http://stackoverflow.com/questions/710756/ie8-var-w-window-open-message-invalid-argument – Micah B. Feb 14 '12 at 19:59
  • I would like to make a small correction: In the function **PrintElem(elem)**, you can use: **Popup($(elem).html());** instead of **Popup($(elem).text());** – shasi kanth Jun 29 '12 at 10:04
  • Passing $("#myDiv").text() as an argument into Popup can be problematic if there are child DIVs inside the one you're trying to print, especially if the ID attribute is set. I had better luck by skipping the dynamic generation of the div, and instead storing what I wanted to print into a big string variable and passing that string directly into Popup. – Stephen Wylie Nov 25 '12 at 07:38
  • I think whether or not this works will depend on how your CSS is set up. If your div is inside a hierarchy of selectors which is used to apply the styles, you might miss some tags. This solution seems fine, but you probably shouldn't expect it to work without manually tweaking the stylesheets – Sprague May 02 '13 at 07:35
  • 5
    @Rahil change it to this: mywindow.document.close(); mywindow.focus(); mywindow.print(); mywindow.close(); – Gaff Aug 19 '13 at 20:40
  • 1
    This SO shows how to make it works in IE http://stackoverflow.com/questions/2555697/window-print-not-working-in-ie – Tuyen Nguyen Sep 25 '13 at 22:30
  • 3
    ^ add newwindow.focus(); to enable print cross-browser. – JackMahoney Sep 30 '13 at 04:00
  • An issue I am having is that when I load additional css via `link`, the css isn't retrieved before print() is called so it tries to print an unstyled page. – wlingke Apr 08 '14 at 19:23
  • 1
    I have an issue with Mozilla and Internet Explorer. same code is running in Google Chrome. Not able to print whole page or multiple page, some part of page is printable others are not what to do? – Hemi May 31 '14 at 06:50
  • @BillPaetzke what if I want to print all those divisions in different pages at a time? – tvshajeer May 07 '15 at 09:00
  • 8
    It sometimes happens if fails to load print preview, maybe when the content to print is quite big (i noticed it only with Chrome while same page prints perfeclty in Firefox, however i dont exclude it might happen in Firefox or other browsers too). The best way i found is to run the print (and close) only after windows is loaded. So after: `mywindow.document.write(data);` Add this: `mywindow.document.write('');` And remove: `mywindow.print();` and `mywindow.close();` – Fabius Nov 07 '15 at 08:58
  • @Fabius having the same issue with Chrome, I tried your suggestion, but it breaks the function. Causing "PrintElem is not defined" in the console. Any way to fix this? – Nikita 웃 Nov 15 '15 at 03:28
  • @CreativeMind You're right, the – Fabius Nov 16 '15 at 01:50
  • Here, how can I remove the header date from the print option. I am using google chrome. – Nirjhar Mandal Dec 23 '15 at 09:26
  • var x = window.screenX, y = window.screenY; var height = document.body.getBoundingClientRect().height; var width = document.body.getBoundingClientRect().width; var mywindow = window.open('', 'my div', 'top='+y+', left='+x+',height='+height+',width='+width); – Gavin Palmer Jan 27 '16 at 16:01
  • I miss the explanation here – hogan Oct 18 '16 at 18:43
  • 2
    This doesn't work in Chrome sometimes. Chrome print preview shows blank page. The image is not loaded before the print preview window is loaded. – live-love Nov 02 '16 at 20:27
  • I've posted a new answer with less serial execution and less designed forced upon users, optional CSS and any browser-valid CSS element selector – MrMesees Feb 15 '17 at 10:41
  • 1
    This BADLY needs an example / fiddle etc – Stuart Apr 26 '18 at 11:03
  • I would upvote this 100 times if I could. Printing is VERY inflexible across browsers, and many other solutions just didn't work. If you want to apply styles to this just add a tag referencing your file's src. – alexr101 Jun 14 '18 at 19:26
  • how to print input elements inside that printable div?. I tried this its not printing input values. – lipon Feb 29 '20 at 12:50
  • it works fine for me in Firefox and chrome – Pramod Kumar May 03 '21 at 11:26
  • @BillPaetzke sir but in my case sometimes i received mywindow null can you please tell me whats's the issue? – Kapil Soni Oct 20 '21 at 12:15
  • Using `innerHTML` does not work if you want to print the contents of Custom Web Components that use shadow DOMs. Because of the nature of shadow DOMs, you won't be able to access their contents to use this method. – pietrorea Feb 17 '22 at 02:02
217

I think there is a better solution. Make your div to print cover the entire document, but only when it's printed:

@media print {
    .myDivToPrint {
        background-color: white;
        height: 100%;
        width: 100%;
        position: fixed;
        top: 0;
        left: 0;
        margin: 0;
        padding: 15px;
        font-size: 14px;
        line-height: 18px;
    }
}
BC.
  • 24,298
  • 12
  • 47
  • 62
  • 5
    Unfortunately, it won't work in IE quite as expected, see this: http://stackoverflow.com/questions/975129/why-does-internet-explorer-8-print-invisible-content – jarek.jpa Oct 23 '12 at 10:31
  • 26
    Content which should overflow onto multiple pages seems to get truncated in Chrome. – Ishmael Smyrnow Jun 12 '15 at 17:28
  • On IE you need to hide the rest of the document. Modifying above as follows will work: @media print { body * { display:none; } .myDivToPrint { display:block; background-color: white; height: 100%; width: 100%; position: fixed; top: 0; left: 0; margin: 0; padding: 15px; font-size: 14px; line-height: 18px; } } – RonnBlack Sep 24 '15 at 21:49
  • 5
    You might need to put z-index: 9999999; in case you have other elements positioned higher. – Adam M. Oct 21 '16 at 12:48
  • 3
    Doesn't work in chrome when there is a vertical scrollbar – John Dec 29 '20 at 04:34
  • This is a really elegant solution. However, for some reason it is printing my div twice in both Edge and Chrome. Any ideas why that might be happening? – Josh Sep 21 '22 at 23:04
47

Note: It's been over 13 years since the plugin mentioned below was written, as noted in the comments. It doesn't work any more due to changed API in jQuery. Feel free to fork and add a pull request!

Although this has been said by @gabe, If you are using jQuery, you can use my printElement plugin.

There's a sample, and more information about the plugin.

The usage is rather straight forward, just grab an element with a jQuery selector and print it:

$("#myDiv").printElement();

I hope it helps!

isherwood
  • 58,414
  • 16
  • 114
  • 157
Erik
  • 870
  • 7
  • 8
  • 32
    8 years later, this will produce "a.browser is undefined" because the .browser call has been removed in jquery 1.9 – KingsInnerSoul Aug 24 '18 at 20:58
  • 1
    14 years later and it still doesn't work :) I haven't touched this code since 2009, you're always welcome to fork and submit a pull request! – Erik Sep 05 '22 at 09:18
36

Using Jquery, simply use this function:

<script>
function printContent(el){
var restorepage = $('body').html();
var printcontent = $('#' + el).clone();
$('body').empty().html(printcontent);
window.print();
$('body').html(restorepage);
}
</script>

Your print button will look like this:

<button id="print" onclick="printContent('id name of your div');" >Print</button>

Edit: If you DO have form data that you need to keep, clone won't copy that, so you'll just need to grab all the form data and replace it after restore as so:

<script>
function printContent(el){
var restorepage = $('body').html();
var printcontent = $('#' + el).clone();
var enteredtext = $('#text').val();
$('body').empty().html(printcontent);
window.print();
$('body').html(restorepage);
$('#text').html(enteredtext);
}
</script>
<textarea id="text"></textarea>
Gary Hayes
  • 1,728
  • 1
  • 15
  • 23
  • 1
    $('body').html(restorepage); will not work because at that time there is no body element available. therefore it will be better to replace it with location.reload(); – Debugger Jun 28 '15 at 06:22
  • No. If you reload the page you will delete any information in forms, or any other settings that may need to be there. It works perfectly fine. If you'll take the time to look at the code, you'll see that var restorepage DOES have all the page information available to make the replacement. Stop trying to edit my code and either test it for yourself or learn what each of the parts of the function do. – Gary Hayes Jun 29 '15 at 00:54
  • This is better. It includes the page design while printing unlike those mentioned above where I still need to put css links from header etc. Thanks! – Jorz Apr 19 '18 at 09:22
  • the way you've passed `el` is terrible, especially since using jQ. Much better to simply pass the `selector` and get rid of the hard coded `#` – RozzA May 16 '18 at 02:13
  • I always used this method today I noticed that it is not working properly on android device (Google Chrome). The printable area of page changes every time and contains some extra parts out of `el`. I think the print command is sent when the body is being restored. – Ali Sheikhpour Jan 01 '19 at 10:29
  • Interesting... have you tried adding a small delay after the window.print(); – Gary Hayes Jan 02 '19 at 03:22
  • is it possible to hide the title and the pade from the printed page ? – Youssef Boudaya Jan 07 '19 at 08:44
  • @AliSheikhpour, this might be because the css code here does not contain any media query or anything else to support design view on different screes ? – Syed Muhammad Munis Ali Oct 01 '20 at 05:37
  • The first click works, but the subsequent clicks on the button don't. Any idea why? – farjam Aug 05 '22 at 19:30
23

i used Bill Paetzke answer to print a div contain images but it didn't work with google chrome

i just needed to add this line myWindow.onload=function(){ to make it work and here is the full code

<html>
<head>
    <script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js"> </script>
    <script type="text/javascript">
        function PrintElem(elem) {
            Popup($(elem).html());
        }

        function Popup(data) {
            var myWindow = window.open('', 'my div', 'height=400,width=600');
            myWindow.document.write('<html><head><title>my div</title>');
            /*optional stylesheet*/ //myWindow.document.write('<link rel="stylesheet" href="main.css" type="text/css" />');
            myWindow.document.write('</head><body >');
            myWindow.document.write(data);
            myWindow.document.write('</body></html>');
            myWindow.document.close(); // necessary for IE >= 10

            myWindow.onload=function(){ // necessary if the div contain images

                myWindow.focus(); // necessary for IE >= 10
                myWindow.print();
                myWindow.close();
            };
        }
    </script>
</head>
<body>
    <div id="myDiv">
        This will be printed.
        <img src="image.jpg"/>
    </div>
    <div>
        This will not be printed.
    </div>
    <div id="anotherDiv">
        Nor will this.
    </div>
    <input type="button" value="Print Div" onclick="PrintElem('#myDiv')" />
</body>
</html>

also if someone just need to print a div with id he doesn't need to load jquery

here is pure javascript code to do this

<html>
<head>
    <script type="text/javascript">
        function PrintDiv(id) {
            var data=document.getElementById(id).innerHTML;
            var myWindow = window.open('', 'my div', 'height=400,width=600');
            myWindow.document.write('<html><head><title>my div</title>');
            /*optional stylesheet*/ //myWindow.document.write('<link rel="stylesheet" href="main.css" type="text/css" />');
            myWindow.document.write('</head><body >');
            myWindow.document.write(data);
            myWindow.document.write('</body></html>');
            myWindow.document.close(); // necessary for IE >= 10

            myWindow.onload=function(){ // necessary if the div contain images

                myWindow.focus(); // necessary for IE >= 10
                myWindow.print();
                myWindow.close();
            };
        }
    </script>
</head>
<body>
    <div id="myDiv">
        This will be printed.
        <img src="image.jpg"/>
    </div>
    <div>
        This will not be printed.
    </div>
    <div id="anotherDiv">
        Nor will this.
    </div>
    <input type="button" value="Print Div" onclick="PrintDiv('myDiv')" />
</body>
</html>

i hope this can help someone

Robert
  • 2,342
  • 2
  • 24
  • 41
21

From here https://forums.asp.net/t/1261525.aspx

<html> 
<head>
    <script language="javascript">
        function printdiv(printpage) {
            var headstr = "<html><head><title></title></head><body>";
            var footstr = "</body>";
            var newstr = document.all.item(printpage).innerHTML;
            var oldstr = document.body.innerHTML;
            document.body.innerHTML = headstr + newstr + footstr;
            window.print();
            document.body.innerHTML = oldstr;
            return false;
        }
    </script>

    <title>div print</title>

</head>

<body>
    //HTML Page //Other content you wouldn't like to print
    <input name="b_print" type="button" class="ipt" onClick="printdiv('div_print');" value=" Print ">

    <div id="div_print">
        <h1 style="Color:Red">The Div content which you want to print</h1>
    </div>
    //Other content you wouldn't like to print //Other content you wouldn't like to print
</body>    
</html>
Husam Ebish
  • 4,893
  • 2
  • 22
  • 38
huston007
  • 1,972
  • 1
  • 16
  • 13
  • 1
    it's needed a modification to split footerStr to 2 parts. because brwoser uses "

    " as the main end of current page. var footstr1 = ""; var footstr2 = "body>"; var footerstr=footstr1 +footstr12;

    – mirzaei Sep 14 '13 at 05:52
19
function printdiv(printdivname) {
    var headstr = "<html><head><title>Booking Details</title></head><body>";
    var footstr = "</body>";
    var newstr = document.getElementById(printdivname).innerHTML;
    var oldstr = document.body.innerHTML;
    document.body.innerHTML = headstr+newstr+footstr;
    window.print();
    document.body.innerHTML = oldstr;
    return false;
}

This will print the div area you want and set the content back to as it was. printdivname is the div to be printed.

Kate Orlova
  • 3,225
  • 5
  • 11
  • 35
Techie
  • 44,706
  • 42
  • 157
  • 243
  • it's needed a modification to split footerStr to 2 parts. because brwoser uses "

    " as the main end of current page. var footstr1 = ""; var footstr2 = "body>"; var footerstr=footstr1 +footstr12;

    – mirzaei Sep 14 '13 at 05:52
  • That's ingenious! But yeah, you do need the hack from mirzaei, otherwhise the body tag breaks and you get broken formatting. With the hack, this works great! You can also even add your own inner wrapper to facilitate special print styles. This should be the accepted answer. – user2662680 Sep 10 '19 at 19:11
13

Create a separate print stylesheet that hides all other elements except the content you want to print. Flag it using 'media="print" when you load it:

<link rel="stylesheet" type="text/css" media="print" href="print.css" />

This allows you to have a completely different stylesheet loaded for printouts.

If you want to force the browser's print dialog to appear for the page, you can do it like this on load using JQuery:

$(function() { window.print(); });

or triggered off of any other event you want such as a user clicking a button.

Carl Russmann
  • 1,719
  • 12
  • 13
  • 2
    Yes that'd work too; it's hard - well, impossible - to know exactly what the scenario is. – Pointy Feb 12 '10 at 21:55
  • I agree that a separate CSS is the ideal solution. And copying the div's contents to a new window is a quick solution. – Bill Paetzke Feb 12 '10 at 22:16
13

I think the solutions proposed so far have the following drawbacks:

  1. The CSS media query solutions assume there is only one div to print.
  2. The javascript solutions work only on certain browsers.
  3. Destroying the parent window content and recreating that creates a mess.

I have improved on the solutions above. Here is something that I have tested that works really well with the following benefits.

  1. Works on all the browsers including IE, Chrome, Safari and firefox.
  2. Doesn't destroy and reload the parent window.
  3. Can print any number of DIV's on a page.
  4. Uses HTML templates to avoid error prone string concatenation.

Key Points to note :

  1. Have to have a onload="window.print()" on the newly created window.
  2. Don't call targetwindow.close() or targetwindow.print() from the parent.
  3. Make sure you do targetwindow.document.close() and target.focus()
  4. I'm using jquery but you can do the same technique using plain javascript as well.
  5. You can see this in action here https://math.tools/table/multiplication. You can print each table separately, by clicking on the print button on the box header.

<script id="print-header" type="text/x-jquery-tmpl">
   <html>
   <header>
       <title>Printing Para {num}</title>
       <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
       <style>
          body {
            max-width: 300px;
          }
       </style>
   </header>
   <body onload="window.print()">
   <h2>Printing Para {num} </h2>
   <h4>https://math.tools</h4>
</script>
<script id="print-footer" type="text/x-jquery-tmpl">
    </body>
    </html>
</script>
<script>
$('.printthis').click(function() {
   num = $(this).attr("data-id");
   w = window.open();
   w.document.write(
                   $("#print-header").html().replace("{num}",num)  +
                   $("#para-" + num).html() +
                   $("#print-footer").html() 
                   );
   w.document.close();
   w.focus();
   //w.print(); Don't do this otherwise chrome won't work. Look at the onload on the body of the newly created window.
   ///w.close(); Don't do this otherwise chrome won't work
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<a class="btn printthis" data-id="1" href="#" title="Print Para 1"><i class="fa fa-print"></i> Print Para 1</a>
<a class="btn printthis" data-id="2" href="#" title="Print Para 2"><i class="fa fa-print"></i> Print Para 2</a>
  
<p class="para" id="para-1">
  Para 1 : Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  

<p class="para" id="para-2">
  Para 2 : Lorem 2 ipsum 2 dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  
Husam Ebish
  • 4,893
  • 2
  • 22
  • 38
dors
  • 1,152
  • 11
  • 19
12

I authored a plugin to address this scenario. I was unhappy with the plugins out there, and set out to make something more extensive/configurable.

https://github.com/jasonday/printThis

Jason
  • 7,612
  • 14
  • 77
  • 127
  • 1
    Thanks a lot for your hard work Jason.....!! Really going to use in my more projects. What a mind blowing plugin man...... Speechless..... –  Aug 16 '18 at 20:28
  • This plugin is really nice, except on mobile browsers on Android (Edge, Chrome & Firefox) it's printing the entire page even though the print preview shows only the div. Is this a bug in the browsers, in Android, or in the plugin? – Vincent May 03 '21 at 23:18
  • @Vincent it's an issue with the library code. It cropped up last year, and unfortunately I haven't had the time to dedicate to getting this fixed, but I am likely to get to it in the next 4-6 weeks. – Jason May 05 '21 at 14:19
  • 1
    That would be great if you could fix that, but it might interest you to know that I pivoted to try printing an iframe instead and the same problem appeared. Trying to print the iframe only on Android ended up still printing the entire page, so maybe knowing that will help you debug your plugin. – Vincent May 06 '21 at 15:15
  • @Vincent - that's really interesting, so you used javascript to attempt to print an iframe without printThis and you ran into the same issue? – Jason May 26 '21 at 01:29
  • Yes, the same issue appeared when I used your plugin to print an iframe. – Vincent May 26 '21 at 22:14
7

The accepted solution wasn't working. Chrome was printing a blank page because it wasn't loading the image in time. This approach works:

Edit: It appears the accepted solution was modified after my post. Why the downvote? This solution works as well.

    function printDiv(divName) {

        var printContents = document.getElementById(divName).innerHTML;
        w = window.open();

        w.document.write(printContents);
        w.document.write('<scr' + 'ipt type="text/javascript">' + 'window.onload = function() { window.print(); window.close(); };' + '</sc' + 'ript>');

        w.document.close(); // necessary for IE >= 10
        w.focus(); // necessary for IE >= 10

        return true;
    }
live-love
  • 48,840
  • 22
  • 240
  • 204
7

If you want to have all the styles from the original document (including inline styles) you can use this approach.

  1. Copy the complete document
  2. Replace the body with the element your want to print.

Implementation:

class PrintUtil {
  static printDiv(elementId) {
    let printElement = document.getElementById(elementId);
    var printWindow = window.open('', 'PRINT');
    printWindow.document.write(document.documentElement.innerHTML);
    setTimeout(() => { // Needed for large documents
      printWindow.document.body.style.margin = '0 0';
      printWindow.document.body.innerHTML = printElement.outerHTML;
      printWindow.document.close(); // necessary for IE >= 10
      printWindow.focus(); // necessary for IE >= 10*/
      printWindow.print();
      printWindow.close();
    }, 1000)
  }   
}
Stefan Norberg
  • 1,137
  • 13
  • 28
  • 3
    I don't know that this is the best solution, but it worked perfectly. Thanks! – BRogers Jun 22 '18 at 22:13
  • 1
    This one worked for me too on Firefox and Chrome, especially if you don't want to lose CSS of the parent page. – ktk Aug 15 '22 at 11:02
6

Its bit late but I found this to be really really nice!!!

function printDiv(divID) {
    //Get the HTML of div
    var divElements = document.getElementById(divID).innerHTML;
    //Get the HTML of whole page
    var oldPage = document.body.innerHTML;

    //Reset the page's HTML with div's HTML only
    document.body.innerHTML = 
       "<html><head><title></title></head><body>" + 
              divElements + "</body>";

    //Print Page
    window.print();

    //Restore orignal HTML
    document.body.innerHTML = oldPage;
          
}
Shedrack
  • 656
  • 7
  • 22
  • 5
    An issue you might encounter with this solution when using a framework like Vue or React is losing reactivity from your DOM when you return from the print screen. – James Stewart Sep 09 '21 at 08:09
4

I know this is an old question, but I solved this problem w jQuery.

function printContents(id) {
    var contents = $("#"+id).html();

    if ($("#printDiv").length == 0) {
      var printDiv = null;
      printDiv = document.createElement('div');
      printDiv.setAttribute('id','printDiv');
      printDiv.setAttribute('class','printable');
      $(printDiv).appendTo('body');
    }

    $("#printDiv").html(contents);

    window.print();

    $("#printDiv").remove();
}

CSS

  @media print {
    .non-printable, .fancybox-outer { display: none; }
    .printable, #printDiv { 
        display: block; 
        font-size: 26pt;
    }
  }
ROOT
  • 11,363
  • 5
  • 30
  • 45
Jazzy
  • 6,029
  • 11
  • 50
  • 74
4

Just use PrintJS

let printjs = document.createElement("script");
printjs.src = "https://printjs-4de6.kxcdn.com/print.min.js";
document.body.appendChild(printjs);

printjs.onload = function (){
    printJS('id_of_div_you_want_to_print', 'html');
}
Paweł Moskal
  • 613
  • 7
  • 10
3

Although @BC answer was the best to print a single page.

But To print multiple pages of A4 size at same time with ctrl+P following solution may help.

@media print{
html *{
    height:0px!important;
    width:0px !important;
    margin: 0px !important;
    padding: 0px !important;
    min-height: 0px !important;
    line-height: 0px !important;
    overflow: visible !important;
    visibility: hidden ;


}


/*assing myPagesClass to every div you want to print on single separate A4 page*/

 body .myPagesClass {
    z-index: 100 !important;
    visibility: visible !important;
    position: relative !important;
    display: block !important;
    background-color: lightgray !important;
    height: 297mm !important;
    width: 211mm !important;
    position: relative !important;

    padding: 0px;
    top: 0 !important;
    left: 0 !important;
    margin: 0 !important;
    orphans: 0!important;
    widows: 0!important;
    overflow: visible !important;
    page-break-after: always;

}
@page{
    size: A4;
    margin: 0mm ;
    orphans: 0!important;
    widows: 0!important;
}}
arslan
  • 565
  • 1
  • 7
  • 25
2

Here is my jquery print plugin

(function ($) {

$.fn.printme = function () {
    return this.each(function () {
        var container = $(this);

        var hidden_IFrame = $('<iframe></iframe>').attr({
            width: '1px',
            height: '1px',
            display: 'none'
        }).appendTo(container);

        var myIframe = hidden_IFrame.get(0);

        var script_tag = myIframe.contentWindow.document.createElement("script");
        script_tag.type = "text/javascript";
        script = myIframe.contentWindow.document.createTextNode('function Print(){ window.print(); }');
        script_tag.appendChild(script);

        myIframe.contentWindow.document.body.innerHTML = container.html();
        myIframe.contentWindow.document.body.appendChild(script_tag);

        myIframe.contentWindow.Print();
        hidden_IFrame.remove();

    });
};
})(jQuery);
karaxuna
  • 26,752
  • 13
  • 82
  • 117
2
  • Open a new window
  • Open the document object of the new window and write into it a simple document containing nothing but the div you've got and necessary html header etc - you may also want to have the document pull in a stylesheet, depending on your content is
  • Put a script in the new page to call window.print()
  • Trigger the script
Pointy
  • 405,095
  • 59
  • 585
  • 614
2

Here is an IFrame solution that works for IE and Chrome:

function printHTML(htmlString) {
    var newIframe = document.createElement('iframe');
    newIframe.width = '1px';
    newIframe.height = '1px';
    newIframe.src = 'about:blank';

    // for IE wait for the IFrame to load so we can access contentWindow.document.body
    newIframe.onload = function() {
        var script_tag = newIframe.contentWindow.document.createElement("script");
        script_tag.type = "text/javascript";
        var script = newIframe.contentWindow.document.createTextNode('function Print(){ window.focus(); window.print(); }');
        script_tag.appendChild(script);

        newIframe.contentWindow.document.body.innerHTML = htmlString;
        newIframe.contentWindow.document.body.appendChild(script_tag);

        // for chrome, a timeout for loading large amounts of content
        setTimeout(function() {
            newIframe.contentWindow.Print();
            newIframe.contentWindow.document.body.removeChild(script_tag);
            newIframe.parentElement.removeChild(newIframe);
        }, 200);
    };
    document.body.appendChild(newIframe);
}
kofifus
  • 17,260
  • 17
  • 99
  • 173
2

Note: This works with jQuery enabled sites only

It is very simple with this cool trick. It worked for me in Google Chrome browser. Firefox wont allow you to print to PDF without a plugin.

  1. First, open the inspector using (Ctrl + Shift + I) / (Cmd + Option + I).
  2. Type this code in the console:

var jqchild = document.createElement('script');
jqchild.src = "https://cdnjs.cloudflare.com/ajax/libs/jQuery.print/1.5.1/jQuery.print.min.js";
document.getElementsByTagName('body')[0].appendChild(jqchild);
$("#myDivWithStyles").print(); // Replace ID with yours
  1. It launches the print dialog. Take a physical print or save it to PDF(in chrome). Done!

The logic is simple. We are creating a new script tag and attaching it in front of closing body tag. We injected a jQuery print extension into the HTML. Change myDivWithStyles with your own Div tag ID. Now it takes cares of preparing a printable virtual window.

Try it on any site. Only caveat is sometimes trickily written CSS can cause missing of styles. But we get the content most of times.

anitag95
  • 307
  • 2
  • 16
Naren Yellavula
  • 7,273
  • 2
  • 29
  • 23
1

In Opera, try:

    print_win.document.write('</body></html>');
    print_win.document.close(); // This bit is important
    print_win.print();
    print_win.close();
Josh
  • 1,794
  • 3
  • 17
  • 31
mirk
  • 11
  • 1
  • This is of course an old answer, but for anyone who comes across this more recently this will not reliably work in modern browsers with https. The print window pops up then immediately closes. – Keith Banner Jan 04 '23 at 18:50
1

Created something generic to use on any HTML element

HTMLElement.prototype.printMe = printMe;
function printMe(query){             
     var myframe = document.createElement('IFRAME');
     myframe.domain = document.domain;
     myframe.style.position = "absolute";
     myframe.style.top = "-10000px";
     document.body.appendChild(myframe);
     myframe.contentDocument.write(this.innerHTML) ;
     setTimeout(function(){
        myframe.focus();
        myframe.contentWindow.print();
        myframe.parentNode.removeChild(myframe) ;// remove frame
     },3000); // wait for images to load inside iframe
     window.focus();
}
//usage
document.getElementById('xyz').printMe();
document.getElementsByClassName('xyz')[0].printMe();

Hope this helps.

Pang
  • 9,564
  • 146
  • 81
  • 122
Gaurav
  • 821
  • 9
  • 11
1

I modified @BillPaetski answer to use querySelector, add optional CSS, remove the forced H1 tag and make title optionally specified or pulled from window. It also doesn't auto-print any more and exposes internals so they can be switched out in wrapper function or as you like.

The only two private vars are tmpWindow and tmpDoc although I believe title, css and elem access may vary it should be assumed all function arguments are private.

Code:
function PrintElem(elem, title, css) {
    var tmpWindow = window.open('', 'PRINT', 'height=400,width=600');
    var tmpDoc = tmpWindow.document;

    title = title || document.title;
    css = css || "";

    this.setTitle = function(newTitle) {
        title = newTitle || document.title;
    };

    this.setCSS = function(newCSS) {
        css = newCSS || "";
    };

    this.basicHtml5 = function(innerHTML) {
        return '<!doctype html><html>'+(innerHTML || "")+'</html>';
    };

    this.htmlHead = function(innerHTML) {
        return '<head>'+(innerHTML || "")+'</head>';
    };

    this.htmlTitle = function(title) {
        return '<title>'+(title || "")+'</title>';
    };

    this.styleTag = function(innerHTML) {
        return '<style>'+(innerHTML || "")+'</style>';
    };

    this.htmlBody = function(innerHTML) {
        return '<body>'+(innerHTML || "")+'</body>';
    };

    this.build = function() {
        tmpDoc.write(
            this.basicHtml5(
                this.htmlHead(
                    this.htmlTitle(title) + this.styleTag(css)
                ) + this.htmlBody(
                    document.querySelector(elem).innerHTML
                )
            )
        );
        tmpDoc.close(); // necessary for IE >= 10
    };

    this.print = function() {
        tmpWindow.focus(); // necessary for IE >= 10*/
        tmpWindow.print();
        tmpWindow.close();
    };

    this.build();
    return this;
}
Usage:
DOMPrinter = PrintElem('#app-container');
DOMPrinter.print();
MrMesees
  • 1,488
  • 19
  • 27
  • Also, it does not copy the values of the `` elements. How can I use this including what the user has typed? – Malcolm Salvador Jul 18 '17 at 02:47
  • @Malky.Kid please think about what you're asking. If you want to print a form, you need to hook blur events on form elements, and set the attribute value, selected, default and innerText of ``, ` – MrMesees Jul 22 '17 at 18:02
  • I've already arrived at a solution by via `.attr('value',)`. I've even done it for textarea (by appending) and checkboxes (`.attr('checked',)`). I'm *sorry* if I wasn't thinking enough about what I was asking. – Malcolm Salvador Jul 23 '17 at 23:29
  • Care to share with the class? maybe a gist or something in the comments. I'll upvote it. – MrMesees Jul 24 '17 at 08:38
1

This should work:

function printDiv(divName) {
     var printContents = document.getElementById(divName).innerHTML;
     var originalContents = document.body.innerHTML;
     document.body.innerHTML = printContents;
     window.print();
     document.body.innerHTML = originalContents;
}
1

HTML > HEAD

  <script type="text/javascript">
    function printDiv() {
        var divToPrint = document.getElementById('printArea');  
    //Firefox was just opening a new window with same content as opener and not performing the printing dialog, so needed to make it open a new instance of the window opener    
        newWin= window.open(self.location.href);
    //We want to format the document appropriately
       newWin.document.write("\<!DOCTYPE html\>\<html lang='es'\>\<head\>\<meta charset='utf-8'\/\>\<meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no'><meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'\>\<meta name='HandheldFriendly' content='true'\/\>");
    //HTML ELEMENTS THAT WE WANT TO HIDE FROM THE PRINTING AREA
        newWin.document.write("<style type='text/css'>@media print{.dataTables_info,.dataTables_filter{height:0!important;width:0!important;margin:0!important;padding:0!important;min-height:0!important;line-height:0!important;overflow:visible!important;visibility:hidden}");
    //General Styling for Printing
        newWin.document.write("body {z-index:100!important;visibility:visible!important;position:relative!important;display:block!important;background-color:lightgray!important;height:297mm!important;width:211mm!important;position:relative!important;padding:0;top:0!important;left:0!important;margin:0!important;orphans:0!important;widows:0!important;overflow:visible!important;page-break-after:always}");
    //Some forced styling in css rules includying page break for a div
        newWin.document.write("body h1{font-size:1em; font-family:Verdana;} a.marked{color:black; text-decoration:none} .pagebreak { page-break-before: always; } ");
        newWin.document.write("@page{size:A4; margin:2em; orphans:0!important;widows:0!important}}</style>\<\/head>\<body>");
        newWin.document.write(divToPrint.innerHTML);
        newWin.document.write("</body></html>");
        newWin.focus();
        newWin.print();
    }
    </script>

HTML > BODY

<div id="printArea">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
<!-- Page break -->
<div class="pagebreak">&nbsp;</div>
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
</div>
Jean G.T
  • 1
  • 10
  • 25
1
function printDomElement(element) {
    element.classList.add("printCss");

    let printId = "printId";
    let name = ".printCss";
    let rules = "-webkit-print-color-adjust:exact;height:100%;width:100%;position:fixed;top:0;left:0;margin:0;";

    var style = document.createElement('style');
    style.id = printId;
    style.media = "print";
    document.getElementsByTagName('head')[0].appendChild(style);

    if (!(style.sheet || {}).insertRule)(style.styleSheet || style.sheet).addRule(name, rules);
    else style.sheet.insertRule(name + "{" + rules + "}", 0);

    window.print();

    setTimeout(() => {
      element.classList.remove("printCss");
      let elem = document.getElementById(printId);
      if (elem) elem.remove();
    }, 500);

  }
Yryskul Turduev
  • 197
  • 1
  • 11
0

The below code copies all relevant nodes that are targeted by the query selector, copies over their styles as seen on screen, since many parent elements used for targeting the css selectors will be missing. This causes a bit of lag if there are a lot of child nodes with a lot of styles.

Ideally you'd have a print style sheet ready, but this is for use cases where there's no print style sheet to be inserted and you wish to print as seen on screen.

If you copy the below items in the browser console on this page it will print all the code snippets on this page.

+function() {
    /**
     * copied from  https://stackoverflow.com/questions/19784064/set-javascript-computed-style-from-one-element-to-another
     * @author Adi Darachi https://stackoverflow.com/users/2318881/adi-darachi
     */
    var copyComputedStyle = function(from,to){
        var computed_style_object = false;
        //trying to figure out which style object we need to use depense on the browser support
        //so we try until we have one
        computed_style_object = from.currentStyle || document.defaultView.getComputedStyle(from,null);

        //if the browser dose not support both methods we will return null
        if(!computed_style_object) return null;

            var stylePropertyValid = function(name,value){
                        //checking that the value is not a undefined
                return typeof value !== 'undefined' &&
                        //checking that the value is not a object
                        typeof value !== 'object' &&
                        //checking that the value is not a function
                        typeof value !== 'function' &&
                        //checking that we dosent have empty string
                        value.length > 0 &&
                        //checking that the property is not int index ( happens on some browser
                        value != parseInt(value)

            };

        //we iterating the computed style object and compy the style props and the values
        for(property in computed_style_object)
        {
            //checking if the property and value we get are valid sinse browser have different implementations
                if(stylePropertyValid(property,computed_style_object[property]))
                {
                    //applying the style property to the target element
                        to.style[property] = computed_style_object[property];

                }   
        }   

    };


    // Copy over all relevant styles to preserve styling, work the way down the children tree.
    var buildChild = function(masterList, childList) {
        for(c=0; c<masterList.length; c++) {
           var master = masterList[c];
           var child = childList[c];
           copyComputedStyle(master, child);
           if(master.children && master.children.length > 0) {
               buildChild(master.children, child.children);
           }
        }
    }

    /** select elements to print with query selector **/
    var printSelection = function(querySelector) {
        // Create an iframe to make sure everything is clean and ordered.
        var iframe = document.createElement('iframe');
        // Give it enough dimension so you can visually check when modifying.
        iframe.width = document.width;
        iframe.height = document.height;
        // Add it to the current document to be sure it has the internal objects set up.
        document.body.append(iframe);

        var nodes = document.querySelectorAll(querySelector);
        if(!nodes || nodes.length == 0) {
           console.error('Printing Faillure: Nothing to print. Please check your querySelector');
           return;
        }

        for(i=0; i < nodes.length; i++) {

            // Get the node you wish to print.
            var origNode = nodes[i];

            // Clone it and all it's children
            var node = origNode.cloneNode(true);

            // Copy the base style.
            copyComputedStyle(origNode, node);

            if(origNode.children && origNode.children.length > 0) {
                buildChild(origNode.children, node.children);
            }

            // Add the styled clone to the iframe. using contentWindow.document since it seems the be the most widely supported version.

            iframe.contentWindow.document.body.append(node);
        }
        // Print the window
        iframe.contentWindow.print();

        // Give the browser a second to gather the data then remove the iframe.
        window.setTimeout(function() {iframe.parentNode.removeChild(iframe)}, 1000);
    }
window.printSelection = printSelection;
}();
printSelection('.default.prettyprint.prettyprinted')
Tschallacka
  • 27,901
  • 14
  • 88
  • 133
0

This is realy old post but here is one my update what I made using correct answer. My solution also use jQuery.

Point of this is to use proper print view, include all stylesheets for the proper formatting and also to be supported in the most browsers.

function PrintElem(elem, title, offset)
{
    // Title constructor
    title = title || $('title').text();
    // Offset for the print
    offset = offset || 0;

    // Loading start
    var dStart = Math.round(new Date().getTime()/1000),
        $html = $('html');
        i = 0;

    // Start building HTML
    var HTML = '<html';

    if(typeof ($html.attr('lang')) !== 'undefined') {
        HTML+=' lang=' + $html.attr('lang');
    }

    if(typeof ($html.attr('id')) !== 'undefined') {
        HTML+=' id=' + $html.attr('id');
    }

    if(typeof ($html.attr('xmlns')) !== 'undefined') {
        HTML+=' xmlns=' + $html.attr('xmlns');
    }

    // Close HTML and start build HEAD
    HTML+='><head>';

    // Get all meta tags
    $('head > meta').each(function(){
        var $this = $(this),
            $meta = '<meta';

        if(typeof ($this.attr('charset')) !== 'undefined') {
            $meta+=' charset=' + $this.attr('charset');
        }

        if(typeof ($this.attr('name')) !== 'undefined') {
            $meta+=' name=' + $this.attr('name');
        }

        if(typeof ($this.attr('http-equiv')) !== 'undefined') {
            $meta+=' http-equiv=' + $this.attr('http-equiv');
        }

        if(typeof ($this.attr('content')) !== 'undefined') {
            $meta+=' content=' + $this.attr('content');
        }

        $meta+=' />';

        HTML+= $meta;
        i++;

    }).promise().done(function(){

        // Insert title
        HTML+= '<title>' + title  + '</title>';

        // Let's pickup all CSS files for the formatting
        $('head > link[rel="stylesheet"]').each(function(){
            HTML+= '<link rel="stylesheet" href="' + $(this).attr('href') + '" />';
            i++;
        }).promise().done(function(){
            // Print setup
            HTML+= '<style>body{display:none;}@media print{body{display:block;}}</style>';

            // Finish HTML
            HTML+= '</head><body>';
            HTML+= '<h1 class="text-center mb-3">' + title  + '</h1>';
            HTML+= elem.html();
            HTML+= '</body></html>';

            // Open new window
            var printWindow = window.open('', 'PRINT', 'height=' + $(window).height() + ',width=' + $(window).width());
            // Append new window HTML
            printWindow.document.write(HTML);

            printWindow.document.close(); // necessary for IE >= 10
            printWindow.focus(); // necessary for IE >= 10*/
console.log(printWindow.document);
            /* Make sure that page is loaded correctly */
            $(printWindow).on('load', function(){                   
                setTimeout(function(){
                    // Open print
                    printWindow.print();

                    // Close on print
                    setTimeout(function(){
                        printWindow.close();
                        return true;
                    }, 3);

                }, (Math.round(new Date().getTime()/1000) - dStart)+i+offset);
            });
        });
    });
}

Later you simple need something like this:

$(document).on('click', '.some-print', function() {
    PrintElem($(this), 'My Print Title');
    return false;
});

Try it.

Ivijan Stefan Stipić
  • 6,249
  • 6
  • 45
  • 78
0

pass the Element to this function to print:

function printElm(elm) {
  var orig = document.body.innerHTML;

  document.body.innerHTML = elm.outerHTML;
  print();
  document.body.innerHTML = orig;
}
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Mahdi
  • 57
  • 6
-1

Same as best answer, just in case you need to print image as i did:

In case you want to print image:

function printElem(elem)
    {
        Popup(jQuery(elem).attr('src'));
    }

    function Popup(data) 
    {
        var mywindow = window.open('', 'my div', 'height=400,width=600');
        mywindow.document.write('<html><head><title>my div</title>');
        mywindow.document.write('</head><body >');
        mywindow.document.write('<img src="'+data+'" />');
        mywindow.document.write('</body></html>');

        mywindow.print();
        mywindow.close();

        return true;
    }
Goran Jakovljevic
  • 2,714
  • 1
  • 31
  • 27
  • You're missing a `load` event on the popup. Without it you'll print a blank page since the image isn't loaded. => `$(popup).load(function(){ popup.focus(); popup.print(); });` – Tim Vermaelen Apr 29 '16 at 11:30
-7

The best way to do it would be to submit the contents of the div to the server and open a new window where the server could put those contents into the new window.

If that's not an option you can try to use a client-side language like javascript to hide everything on the page except that div and then print the page...

Sonny Boy
  • 7,848
  • 18
  • 76
  • 104