Print <div id="printarea"></div> only?
Asked Answered
L

35

552

How do I print the indicated div (without manually disabling all other content on the page)?

I want to avoid a new preview dialog, so creating a new window with this content is not useful.

The page contains a couple of tables, one of them contains the div I want to print - the table is styled with visual styles for the web, that should not show in print.

Litha answered 22/1, 2009 at 12:9 Comment(1)
#2255791 this link works perfectDandiprat
T
1018

Here is a general solution, using CSS only, which I have verified to work.

@media print {
  body {
    visibility: hidden;
  }
  #section-to-print {
    visibility: visible;
    position: absolute;
    left: 0;
    top: 0;
  }
}

There's a Code Sandbox if you want to see this in action. Click the Open In New Window button above the preview; then you can use the browser's Print command to see a preview of the printout.

Alternative approaches aren't so good. Using display is tricky because if any element has display:none then none of its descendants will display either. To use it, you have to change the structure of your page.

Using visibility works better since you can turn on visibility for descendants. The invisible elements still affect the layout though, so I move section-to-print to the top left so it prints properly.

Torsibility answered 11/4, 2010 at 22:39 Comment(41)
#section_to_print should work better with position:static; instead of position:absolute;Clavicytherium
How is it better? Multi-page printing, perhaps?Torsibility
this is by far the fastest and cleanest way, i wonder why this answer didn't get the most votes -.-Singlehearted
A problem to watch out for with this solution is that you can end up printing thousands of blank pages in some cases. In my case I was able to solve this by using some additional display:none styling for selected items but perhaps a more general solution is achievable by some combination of also forcing heights, overflow:none and absolute positioning for all divs or something.Dulsea
You're right: if the content spans multiple pages then you have to be careful with the CSS. And test in every possible browser. :\Torsibility
This is a great start but I had two troubles with it: for one if any of the element's parents established its own relative/absolute positioning the content would still be offset unless I used position:fixed instead. However, Chrome and Safari would also truncate content, especially after the first page. So my final workaround was to set both the target and all its parents to overflow:visible; position:absolute !important; top:0;left:0Ilowell
@Bennett thanks for this excellent solution. But I am getting an extra blank page when I print. How can we avoid that?Thee
@Thee First step: test results on various different browsers, to see if the problem is browser-dependent.Torsibility
@Bennett Problem is not browser dependent. I can see it in Chrome, FF and IE.Thee
@Thee I created a minimal Plunk that works for me in Chrome (it prints out a single page). Maybe you could create a Plunk that demonstrates the problem, and we could figure out what's going on.Torsibility
Curious, why does section-to-print need to be present twice?Pamalapamela
@Pamalapamela The second rule makes the print section and its contents visible. The third rule moves the print section to the top-left corner. You could refactor the rules to reduce the selector duplication, but you'd have to duplicate the visibility declaration instead.Torsibility
@BennettMcElwee No, I mean why does the second rule have to reference the Id selector twice?Pamalapamela
@Pamalapamela #section-to-print matches the section itself; #section-to-print * matches each sub-element of the section. So that rule just makes the section and all its contents visible.Torsibility
@BennettMcElwee: What if the section-to-print div is on the bottom right corner of the page ? And the div position is relative meaning it adjusts according to the page size ?Advertence
@Advertence When printed, it will move to the top left.Torsibility
As noted above, this does not work on more complex pages with lots of content. If you need to completely block content from displaying using display:none, you may be better off with a js solutionAsch
You can try a JavaScript solution, but that won't work if your user uses the browser's Print command.Torsibility
But it avoids the css styles from external bootstrap file.Conditional
It is still using the Bootstrap styles. Bootstrap is setting the text to black when printing, via the rule in print.less.Torsibility
Can you explain how I use this in my page? I have a master CSS fileRagman
@JamesWierzba (Not sure what you mean by a master CSS file) Put the CSS snippet in your CSS file and change #section-to-print to a selector that selects the section you want to print.Torsibility
6 years later this is still a perfect solution. I used this in an AngularJS application with window.print() and had no issues.Undergird
So I tried this and it works, but I don't understand how. I didn't apply #section-to-print to anything in my html. How exactly is this able to print exactly what I need?Clockmaker
It is possible that the bit you wanted already had visibility: visible set by some other CSS.Torsibility
I feel like body *:not(#section-to-print *) {visibility: hidden;} would be more elegant as it wouldn't require overriding things twice. However, it doesn't seem to work at all for me. Oh well.Underlie
If there are absolutely placed elements in the section to be printed, you have to set them to hidden in the media print section of the css in order for this solution to work. The Material Design LiteTextField component is an example of this issue.Mattie
I improved it a little bit, if you wanna hide the printable stuff. #section-to-print{ visibility:hidden; height:0px; } @media print { body * { visibility: hidden; } #section-to-print, #section-to-print * { visibility: visible; } #section-to-print { position: absolute; left: 0; top: 0; } } Foucault
@ShahAbazKhan If you want to hide the printable stuff on the screen, then simpler solutions are possible. But it's a bit weird: it means you'd see something on the screen, select "Print", and something completely different would appear at your printer.Torsibility
This fails when we are using div with the scrollbarArlyne
@JeevanRoydsouza can you give an example?Torsibility
When we have section-to-print in @media print with .section-to-print, .section-to-print * { visibility: visible; } .section-to-print { position: fixed; left: 0; top: 0; display: block; width: auto; overflow-y: scroll; } and out side media print css .section-to-print{ height: 80%; overflow-y: scroll; border: 1px solid grey; }Arlyne
When we have section-to-print is a div with the scrollbar, then scrollbar is not coming in the print pageArlyne
To hide the printed area, use: @media screen { #section-to-print { display: none; } }Saguenay
This solution works perfect, but unfortunately in my case I have page breaks (page-break-after:always) which is not working, it is because of position absolute. Any idea how to avoid using position absolute.Guth
After spending 2 hours on finding a solution this workedOstensible
Why is #section-to-print * necessary? It seems solely #section-to-print { visibility: visible; } also works, since visibility inherits?Soutor
@JyunhaoShih You are right! You are the first person in 10 years to suggest that improvement. (Although dudeNumber4 hinted at it.) Thanks -- I don't know how that escaped me for so long.Torsibility
@BennettMcElwee hiding body means you can't print also other pages which don't contain the #section-to-print (because the body is always hidden now). I suppose you can use white background on the #section-to-print in that case instead of hiding the body. Maybe this is more evident in SPA apps like in react, because in my case all CSS files there were loaded together.Screwworm
@GiorgiMoniava Yes, the whole idea here is that only #section-to-print will be printed, so if a page doesn't contain it then nothing will be printed. There are many ways you could easily turn this on or off, e.g. change the selectors to body.print-section and body.print-section #section-to-print, then add/remove the print-section class to en/disable the feature.Torsibility
This answer is stayed valuable even in the era of ChatGPT.Brink
H
296

I have a better solution with minimal code.

Place your printable part inside a div with an id like this:

<div id="printableArea">
      <h1>Print me</h1>
</div>

<input type="button" onclick="printDiv('printableArea')" value="print a div!" />

Then add an event like an onclick (as shown above), and pass the id of the div like I did above.

Now let's create a really simple javascript:

function printDiv(divId) {
     var printContents = document.getElementById(divId).innerHTML;
     var originalContents = document.body.innerHTML;

     document.body.innerHTML = printContents;

     window.print();

     document.body.innerHTML = originalContents;
}

Notice how simple this is? No popups, no new windows, no crazy styling, no JS libraries like jquery. The problem with really complicated solutions (the answer isn't complicated and not what I'm referring to) is the fact that it will NEVER translate across all browsers, ever! If you want to make the styles different, do as shown in the checked answer by adding the media attribute to a stylesheet link (media="print").

No fluff, lightweight, it just works.

Helotism answered 23/9, 2011 at 17:16 Comment(24)
@Kevin i try this for form but it print empty form (without data) and i need a filled form to be print before submittingGave
This works perfectly fine in Fierfox and Chrome. For some reasons , IE hangs when opening and writing down the contents.Afrikander
@Kevin: Great solution.. However it does not capture the background colors and styles? It prints only plain text. Any modification possible for getting the colors and styles as well?Ladder
@asprin warning! This is not mess free code. Using innerHTML to wipe out then recreate the whole body is fine for simple pages, but with more advanced customizations (menus, slideshows, etc.) it could erase some dynamic behaviors added by other scripts.Bassorilievo
This solution is not going to work in any complex page where the elements in printable area depend on styles and/or position of parent elements. If you extract the printable div, it may look totally different because all of the parents are now missing.Rajiv
Sadly doesn't work well in Chrome if you close the Print preview window then try to do a jQuery .click. It's a shame, because the code is so lightweight.Motherhood
@Kevin Thank you very much. This is indeed the solution for my problem. No need to mess around with my code either, great answer! +1Canning
I like the approach but against having to reload the entire dom just to print. In a complex page with 'state' this would be very tricky. I have been inspired by this code and come up with an alternative: github.com/mikeljames/printmeMidwest
@mike You are not reloading anything, This is strictly manipulating DOM. You are storing the markup in a variable, printing the page and putting it back. I understand your hesitancy in doing this, but it is important to realize there is no loading taking place. You are simply manipulating DOMHelotism
@KevinFlorida When I say Reload I essentially mean repaint, the dom is slow, using css to hide the elements is faster: #2447809Midwest
@Christophe: My page on ASP.NET very heavy and contains a lot of dynamic content. Despite this, the printing function works great. The idea itself is simple and ingenious, thanks Kevin Florida!Timmie
@BorisGappov a very simple example with just one click event to prove my point: jsfiddle.net/dc7voLzt I'll say it again: this is not mess-free code! The issue is not with the print itself, it's about restoring the original page!Bassorilievo
with this solution when i click to print the page and close the preview window i cant click to print again, any idea why print() only works once ?, im using React with Redux.Breast
@Kevin I tried this code but having one problem that is page breaks are not working in print. I have page-break-after: always; in child elements of print div but still print does not have any page break :(Gibeon
Hi @KevinFlorida I tried your code and it works only once. after closing and clicking again the button it shows error. I'm using vuejs2 Uncaught TypeError: Failed to execute 'contains' on 'Node': parameter 1 is not of type 'Node'.Ortrude
If your html has select tag then it's not display the selected option while printing.Algetic
What if I want to send a URL in the button and print the pdf of the URL? Is this possible? This is for the archive page. Note: I don't want to redirect to the URL I am sending.Gaiter
It didn't work in my case. I have a form to be printed and I tried ur trick. But it is giving me some errors like: Cannot set property 'onclick' of null and Uncaught (in promise) Error: Not enough parameters. BTW I am on AngularJSFlanch
I used location.reload(); at the last line to fix the onclick problem and this this way, the answer is totally fast and satisfying for me, thanksAnelace
I tried all options, this one works on Chrome. To make sure the switch back is working a location.reload() should be usedIcelandic
Plenty of scope to add styles before printing and restore them afterwards with this clear simple piece of code. Handles pages delivered by PHP just fine. Maybe onfocus() location.reload() for when the print dialogue is cancelled will help.Northway
This is quick and good solution for small to medium sized pages.. well done!!Canoodle
Working fine for me in Chrome.Vaporizer
With me it works really best compare to other solutionsEadith
I
131

All the answers so far are pretty flawed - they either involve adding class="noprint" to everything or will mess up display within #printable.

I think the best solution would be to create a wrapper around the non-printable stuff:

<head>
    <style type="text/css">

    #printable { display: none; }

    @media print
    {
        #non-printable { display: none; }
        #printable { display: block; }
    }
    </style>
</head>
<body>
    <div id="non-printable">
        Your normal page contents
    </div>

    <div id="printable">
        Printer version
    </div>
</body>

Of course this is not perfect as it involves moving things around in your HTML a bit...

Ilise answered 22/1, 2009 at 12:28 Comment(10)
I think you're right, but how do I kill the styling of the table surrounding the div (if thats possible to remove the styling - I can print the table and exclude the rest of the content quite easilyLitha
I uses Javascript to pickup the needed content and the CSS like aboveLitha
I prefer using semantic HTML. Print formatting should ideally be handled by CSS. See my answer for how to do this: #469381Torsibility
Agree with Bennett, using visibility instead of display is a much cleaner solutionInterject
I made a really simple solution at lower on this thread which I think will suit the asker's needs better. It doesn't rely on a print stylesheet, can be recycled all over your website, and is incredibly lightweight.Helotism
@BennettMcElwee But that doesn't allow you to dynamically change which parts of the page are printable based on other conditions, which is the only reason I imagine someone would be looking to JavaScript to achieve this goal.Foliole
@emodendroket Quite right, if you want to do dynamic things you'll need JavaScript.Using my solution, for instance, you could use JS to assign the section-to-print ID to whichever part of the page you want to print. That takes care of the dynamic aspect. Then the CSS takes care of the presentation (printing) aspect, as it should.Torsibility
@BennettMcElwee Sure. I agree, but I don't understand how that differs from this answer.Foliole
@emodendroket This answer requires you to structure the page in a certain way, and it requires you to create a separate "printer version" that isn't shown on-screen at all. (Thus it doesn't even answer the OP's question!)Torsibility
@BennettMcElwee Oh, I see what you mean. Yeah, you're right that styling body as hidden is probably cleaner.Foliole
C
117

With jQuery it's as simple as this:

w=window.open();
w.document.write($('.report_left_inner').html());
w.print();
w.close();
Complicated answered 6/11, 2009 at 12:57 Comment(10)
This is pretty cool, altho it shows up in Chrome as a blocked popup.Embraceor
the trick is to call it on user-generated event such as on mouse click. you can also add after first line: if(!w)alert('Please enable pop-ups');Complicated
Definitely adding this to my toolkit. It is a quick and simple solution.Sheepshank
OP wanted not to include the web-styling, but I suppose we can add few <style> tagsComplicated
has anyone got this working on IE11? It just opens a window then closes it immediately. Works in Chrome, FF and safari though.Lapham
Thank you but I have a question. All objects in page acts like left-to-right. Is there a way to prevent it ? @ComplicatedFehr
I lost the css while printing with this, is there any way to maintain css?Alexi
@MoxetKhan, this post has a solution with css vevlo.com/how-to-print-div-content-using-javascriptRhombencephalon
Here's a implementation in pure javascript: function print(id) { var content = document.getElementById(id).cloneNode(true); var w = window.open(); w.document.head.innerHTML = document.getElementsByTagName("head")[0].innerHTML; w.document.body.append(content); w.print(); w.close(); }Emilemile
@Complicated sir i received null after window.open can you tell me how to fix?Sanferd
S
22

Could you use a print stylesheet, and use CSS to arrange the content you wanted printed? Read this article for more pointers.

Sauternes answered 22/1, 2009 at 12:12 Comment(5)
I do have a print style sheet - trying to avoid putting a style rule in all other content...Litha
I do have a table with styling on, containg the div in question, If I set the table to display:none - can I still display the div?Litha
I think so yes, and you could try marking the rule as !important to boost it!Sauternes
if the table isn't displayed it won't matter even if the div is set to 'display: awesome;'. The parent is hidden and so are the children. Is this a situation where you need a table or is it just for page layout?Cuellar
"Boom, headshot!" by table layouts. =|Yuan
P
18

I didn't really like any of these answers as a whole. If you have a class (say printableArea) and have that as an immediate child of body, then you can do something like this in your print CSS:

body > *:not(.printableArea) {
    display: none;
}

//Not needed if already showing
body > .printableArea {
    display: block;
}

For those looking for printableArea in another place, you would need to make sure the parents of printableArea are shown:

body > *:not(.parentDiv),
.parentDiv > *:not(.printableArea) {
    display: none;
}

//Not needed if already showing
body > .printableArea {
    display: block;
}

Using the visibility can cause a lot of spacing issues and blank pages. This is because the visibility maintains the elements space, just makes it hidden, where as display removes it and allows other elements to take up its space.

The reason why this solution works is that you are not grabbing all elements, just the immediate children of body and hiding them. The other solutions below with display css, hide all the elements, which effects everything inside of printableArea content.

I wouldn't suggest javascript as you would need to have a print button that the user clicks and the standard browser print buttons wouldn't have the same effect. If you really need to do that, what I would do is store the html of body, remove all unwanted elements, print, then add the html back. As mentioned though, I would avoid this if you can and use a CSS option like above.

NOTE: You can add whatever CSS into the print CSS using inline styles:

<style type="text/css">
@media print {
   //styles here
}
</style>

Or like I usually use is a link tag:

<link rel="stylesheet" type="text/css" media="print" href="print.css" />
Perforate answered 23/7, 2013 at 15:2 Comment(8)
What if the div you want to print is not "an immediate child of body"? I'm trying to do this in vue.js.. But I'm getting a lot of blank pages when using the accepted answer.Saguenay
@svenema, you can use any CSS you want. This was just an example.Perforate
hmm, still, when I try this, there are indeed no additional blank pages, but the printableArea div is also not showing; I just have 1 empty blank page when I use this code.Saguenay
I found out that it is indeed because the printableArea div is not a direct child of the body tag, when I make it a direct child your solution works; however, in my case I cannot make the printableArea a direct child. Is there a way around this?Saguenay
still.. when the printableArea div is not a direct child of the body tag I get a blank page only. Could you post a fully working example perhaps?Saguenay
If you post your example to jsfiddle or something similar, I can help fix.Perforate
Sorry for the delay. The site wasn't working when I had time to look and just got back to this. Basically you need to specify the parent in your CSS. Something like jsfiddle.net/sn79fow1Perforate
Great stuff, very much appreciated! I've been playing with it for a few hours now, learning about the selectors and pseudo classes. But I've not been able to figure out if there is a way to place the printableArea in an arbitrary location and still have it only print that specific class.Saguenay
D
10
  1. Give whatever element you want to print the id printMe.

  2. Include this script in your head tag:

    <script language="javascript">
        var gAutoPrint = true;
    
        function processPrint(){
    
        if (document.getElementById != null){
        var html = '<HTML>\n<HEAD>\n';
        if (document.getElementsByTagName != null){
        var headTags = document.getElementsByTagName("head");
        if (headTags.length > 0) html += headTags[0].innerHTML;
        }
    
        html += '\n</HE' + 'AD>\n<BODY>\n';
        var printReadyElem = document.getElementById("printMe");
    
        if (printReadyElem != null) html += printReadyElem.innerHTML;
        else{
        alert("Error, no contents.");
        return;
        }
    
        html += '\n</BO' + 'DY>\n</HT' + 'ML>';
        var printWin = window.open("","processPrint");
        printWin.document.open();
        printWin.document.write(html);
        printWin.document.close();
    
        if (gAutoPrint) printWin.print();
        } else alert("Browser not supported.");
    
        }
    </script>
    
  3. Call the function

    <a href="javascript:void(processPrint());">Print</a>
    
Dartmoor answered 8/5, 2009 at 23:37 Comment(1)
This is a good job. But way too complicated and will not work properly cross-browser (especially older browsers). I suggest you take a look at my solution below.Helotism
B
10

Step 1: Write the following javascript inside your head tag

<script language="javascript">
function PrintMe(DivID) {
var disp_setting="toolbar=yes,location=no,";
disp_setting+="directories=yes,menubar=yes,";
disp_setting+="scrollbars=yes,width=650, height=600, left=100, top=25";
   var content_vlue = document.getElementById(DivID).innerHTML;
   var docprint=window.open("","",disp_setting);
   docprint.document.open();
   docprint.document.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"');
   docprint.document.write('"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">');
   docprint.document.write('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">');
   docprint.document.write('<head><title>My Title</title>');
   docprint.document.write('<style type="text/css">body{ margin:0px;');
   docprint.document.write('font-family:verdana,Arial;color:#000;');
   docprint.document.write('font-family:Verdana, Geneva, sans-serif; font-size:12px;}');
   docprint.document.write('a{color:#000;text-decoration:none;} </style>');
   docprint.document.write('</head><body onLoad="self.print()"><center>');
   docprint.document.write(content_vlue);
   docprint.document.write('</center></body></html>');
   docprint.document.close();
   docprint.focus();
}
</script>

Step 2: Call the PrintMe('DivID') function by an onclick event.

<input type="button" name="btnprint" value="Print" onclick="PrintMe('divid')"/>
<div id="divid">
here is some text to print inside this div with an id 'divid'
</div>
Bound answered 9/4, 2013 at 11:38 Comment(2)
This is the one! Used it for a Modal and Gallerys. No Javascript errors after closing. Really helpful especially when u use modals which are longer than one page. Nicely wraps it up. Perfect for people who want to print to store.Battery
It does not copy the CSS within the HTML.Amias
S
7
<script type="text/javascript">
   function printDiv(divId) {
       var printContents = document.getElementById(divId).innerHTML;
       var originalContents = document.body.innerHTML;
       document.body.innerHTML = "<html><head><title></title></head><body>" + printContents + "</body>";
       window.print();
       document.body.innerHTML = originalContents;
   }
</script>

Subsoil answered 10/10, 2013 at 9:22 Comment(2)
look nice but you loose all javascript bindings and other after printJuice
It is printing without css.Alexi
J
6

hm ... use the type of a stylsheet for printing ... eg:

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

print.css:

div { display: none; }
#yourdiv { display: block; }
Jelsma answered 22/1, 2009 at 12:13 Comment(8)
This will not work if the document is not DIV-based or #yourdiv also includes further DIVs.Cardie
#yourdiv * { display: ... } if you place this on top of the page and have an up-to-date browser you can then work with more selectors to hide away non divsJelsma
"#yourdiv * { display: ... }" - what should the ... be without breaking the layout?Ilise
This would display inline elements also as block elements. But “#yourdiv, #yourdiv div { display:block }” will do it.Cardie
@dittodhole - think about it for a minute. What could you put in there that won't break the layout within #yourdiv?Ilise
run-in - but not supported with common browsers. only working values are: inline, block and none (list-item with ie > 5). so i would say: it depends on the layout! but i would prefer Gumbo's solution with my not-knowing-what's-on-the-page viewJelsma
The trouble is, with almost any layout you have a mix of block and inline. Even something really simple like this: <p>This <b>is</b> broken.</p> <p>If you choose inline <b>or</b> block</p>Ilise
therefore i would tend to build up 2 different mother-divs like here #469381Jelsma
F
6

The Best way to Print particular Div or any Element

printDiv("myDiv");

function printDiv(id){
        var printContents = document.getElementById(id).innerHTML;
        var originalContents = document.body.innerHTML;
        document.body.innerHTML = printContents;
        window.print();
        document.body.innerHTML = originalContents;
}
Facility answered 9/1, 2020 at 14:45 Comment(3)
This solution of overwriting the whole page sometimes doesn't work, for example in APEX the menu stops working.Hearse
hmm, may your event listener stop working, you can write event like $(document).on("click","#element",function(){ /*some code*/ }); , may it will help you or plz, describe or show your example... :)Funnyman
menu in oracle apex stops working after printing. ;(Hearse
V
6

Without CSS clowning, html and pure javascript with iframe does its work best. Then simply click the text, you want to print. Current example for id elements with text content;

html body:

<div id="monitor" onclick="idElementPrint()">text i want to print</div>

pure javascript:

//or: monitor.textContent = "click me to print textual content";

const idElementPrint = () => {
    let ifram = document.createElement("iframe");
    ifram.style = "display:none";
    document.body.appendChild(ifram);
    pri = ifram.contentWindow;
    pri.document.open();
    pri.document.write(monitor.textContent);
    pri.document.close();
    pri.focus();
    pri.print();
    }
Viehmann answered 10/11, 2020 at 16:51 Comment(0)
L
3

printDiv(divId): A generalized solution to print any div on any page.

I had a similar issue but I wanted (a) to be able to print the whole page, or (b) print any one of several specific areas. My solution, thanks to much of the above, allows you to specify any div object to be printed.

The key for this solution is to add an appropriate rule to the the print media style sheet so that the requested div (and its contents) will be printed.

First, create the needed print css to suppress everything (but without the specific rule to allow the element you want to print).

<style type="text/css" media="print">
   body {visibility:hidden; }
   .noprintarea {visibility:hidden; display:none}
   .noprintcontent { visibility:hidden; }
   .print { visibility:visible; display:block; }
</style>

Note that I have added new class rules:

  • noprintarea allows you to suppress the printing of elements within your div- both the content and the block.
  • noprintcontent allows you to suppress the printing of elements within your div- the content is suppressed but and the allocated area is left empty.
  • print allows you to have items that show up in the printed version but not on the screen page. These will normally have "display:none" for the screen style.

Then insert three JavaScript functions. The first merely toggles the print media style sheet on and off.

function disableSheet(thisSheet,setDisabled)
{ document.styleSheets[thisSheet].disabled=setDisabled; }   

The second does the real work and the third cleans up afterward. The second (printDiv) activates the print media style sheet, then appends a new rule to allow the desired div to print, issues the print, and then adds a delay before the final housekeeping (otherwise the styles can be reset before the print is actually done.)

function printDiv(divId)
{
  //  Enable the print CSS: (this temporarily disables being able to print the whole page)
  disableSheet(0,false);
  //  Get the print style sheet and add a new rule for this div
  var sheetObj=document.styleSheets[0];  
  var showDivCSS="visibility:visible;display:block;position:absolute;top:30px;left:30px;";
  if (sheetObj.rules) { sheetObj.addRule("#"+divId,showDivCSS); }
  else                { sheetObj.insertRule("#"+divId+"{"+showDivCSS+"}",sheetObj.cssRules.length); }
  print();
  //  need a brief delay or the whole page will print
  setTimeout("printDivRestore()",100);  
}

The final functions deletes the added rule and sets the print style again to disabled so the whole page can be printed.

function printDivRestore()
{
  // remove the div-specific rule
  var sheetObj=document.styleSheets[0];  
  if (sheetObj.rules) { sheetObj.removeRule(sheetObj.rules.length-1); }
  else                { sheetObj.deleteRule(sheetObj.cssRules.length-1); }
  //  and re-enable whole page printing
  disableSheet(0,true);
}

The only other thing to do is to add one line to your onload processing so that the print style is initially disabled thereby allowing whole page printing.

<body onLoad='disableSheet(0,true)'>

Then, from anywhere in your document, you can print a div. Just issue printDiv("thedivid") from a button or whatever.

A big plus for this approach it provides a general solution to printing selected content from within a page. It also allows use of existing styles for elements that are printed - including the containing div.

NOTE: In my implementation, this must be the first style sheet. Change the sheet references (0) to the appropriate sheet number if you need to make it later in the sheet sequence.

Landseer answered 22/1, 2011 at 21:36 Comment(0)
S
3

All answers have trade-offs and cannot be used for all cases. They fall into 3 categories:

  1. Use a printing style sheet. This requires building the whole website to be print-aware.

  2. Hide all elements in <body> and only show the printable element. This works nicely for simple pages, but it is tricky for complex pages.

  3. Open a new window with the content of the printable element or replace the <body> content with the content of the element. The first will lose all styles, and the second is messy and can break events.

There is no one solution that will work well for all cases, so it is good to have all those choices and I'm adding another solution that works much better in some cases. This solution is a hybrid of two categories: hide all content of <body>, then copy the content of the printable element to a new <div> and append it to <body>. After printing, remove the newly added <div> and show the content of <body> back. This way, you won't lose the styles or events, and you don't mess up with opening a new window. But like all other solutions, it won't work well for all cases. If your printable element's styles depends on its parents, you'll lose those styles. It is still much easier to style your printable elements independently from its parents than having to style the entire website for printing.

The only hurdle is figuring out how to select all content of <body>. For simple pages, the generic style body>* will do the trick. However, complex pages usually have <script> tags at the end of body' and also some `s that are used for dialogs, etc. Hiding all those is fine, but you don't want to show them after printing.

In my case, I build all may websites with three sections inside <body>: <header>, <footer>, and between them <div id="Content">. Adjust the first line of the function below for your case:

function PrintArea(selector) {
    //First hide all content in body.
    var all = $("body > header, body > #Content, body > footer")
    all.hide();
    //Append a div for printing.
    $("body").append('<div id="PrintMe">');
    //Copy content of printing area to the printing div.
    var p = $("#PrintMe");
    p.html($(selector).html());
    //Call the print dialog.
    window.print();
    //Remove the printing div.
    p.remove();
    //Show all content in body.
    all.show();
}

I used jQuery because it's cleaner and simpler, but you can easily convert it to vanilla JavaScript if you like. And of course, you can change var to let as recommended for the local variables.

Safire answered 9/6, 2021 at 17:37 Comment(0)
E
3

My approach - Simple CSS and JS. Works on React/NextJS too.

  const handlePrint = e => {
    e.preventDefault();
    const bodyElement = document.getElementsByTagName('body')[0];

    bodyElement.classList.add('printing');
    window.print();
    bodyElement.classList.remove('printing');
  };

.printing {
  visibility:hidden;
}

.printView {
  visibility:visible;
}

.printing .printView {
  /* You can have any CSS here to make the view better on print */
  position:absolute;
  top:0;
}

What it does?

  1. Adds .printing class to body element. With CSS we hide all body content with visibility:hidden;
  2. At the same time, we keep CSS ready with .printing .printView to have any kind of view we want for the print area.
  3. Trigger window.print();
  4. Remove .printing class from the body element when the user cancels / prints.

Example:


<button onclick="handlePrint">
    Download PDF
</button>

<div>
    <h1>Don't print this</h1>

    <div class="printView">Print this</div>
</div>

Let me know if this helps anyone :)

Escapee answered 7/7, 2022 at 10:25 Comment(0)
R
2

Sandro's method works great.

I tweaked it to allow for allowing multiple printMe links, particularily to be used in tabbed pages and expanding text.

function processPrint(printMe){ <-- calling for a variable here

var printReadyElem = document.getElementById(printMe); <-- removed the quotes around printMe to ask for a variable

<a href="javascript:void(processPrint('divID'));">Print</a> <-- passing the div ID to be printed on to the function to turn the printMe variable into the div ID. single quotes are needed

Rarefy answered 19/6, 2009 at 19:58 Comment(0)
T
2

@Kevin Florida If you have multiple divs with same class, you can use it like this:

 <div style="display:none">
   <div id="modal-2" class="printableArea">
     <input type="button" class="printdiv-btn" value="print a div!" />
   </div>
 </div>

i was using Colorbox inner content type

$(document).on('click', '.printdiv-btn', function(e) {
    e.preventDefault();

    var $this = $(this);
    var originalContent = $('body').html();
    var printArea = $this.parents('.printableArea').html();

    $('body').html(printArea);
    window.print();
    $('body').html(originalContent);
});
Teryl answered 15/9, 2015 at 8:3 Comment(0)
R
2

In my case I had to print a image inside a page. When I used the solution voted, I had 1 blank page and the other one showing the image. Hope it will help someone.

Here is the css I used:

@media print {
  body * {
    visibility: hidden;
  }

  #not-print * {
    display: none;
  }

  #to-print, #to-print * {
    visibility: visible;
  }

  #to-print {
    display: block !important;
    position: absolute;
    left: 0;
    top: 0;
    width: auto;
    height: 99%;
  }
}

My html is:

<div id="not-print" >
  <header class="row wrapper page-heading">

  </header>

  <div class="wrapper wrapper-content">
    <%= image_tag @qrcode.image_url,  size: "250x250" , alt: "#{@qrcode.name}" %>
  </div>
</div>

<div id="to-print" style="display: none;">
  <%= image_tag @qrcode.image_url,  size: "300x300" , alt: "#{@qrcode.name}" %>
</div>
Radiotelephony answered 17/6, 2016 at 14:18 Comment(0)
V
2

One more approch without affecting current page and it also persist the css while printing. Here selector must be specific div selector which content we need to print.

printWindow(selector, title) {
   var divContents = $(selector).html();
   var $cssLink = $('link');
   var printWindow = window.open('', '', 'height=' + window.outerHeight * 0.6 + ', width=' + window.outerWidth  * 0.6);
   printWindow.document.write('<html><head><h2><b><title>' + title + '</title></b></h2>');
   for(var i = 0; i<$cssLink.length; i++) {
    printWindow.document.write($cssLink[i].outerHTML);
   }
   printWindow.document.write('</head><body >');
   printWindow.document.write(divContents);
   printWindow.document.write('</body></html>');
   printWindow.document.close();
   printWindow.onload = function () {
            printWindow.focus();
            setTimeout( function () {
                printWindow.print();
                printWindow.close();
            }, 100);  
        }
}

Here provided some time out show that external css get applied to it.

Vulva answered 15/2, 2018 at 5:22 Comment(1)
CSS sometimes take time to load, this approach is what I was looking to reload the page before printing. ThanksNahshon
S
2
It's better solution. You can use it Angualr/React

Html

 <div class="row" id="printableId">
      Your html 
    </div>

Javascript

   function printPage(){
        
        var printHtml = window.open('', 'PRINT', 'height=400,width=600');
    
        printHtml.document.write('<html><head>');
        printHtml.document.write(document.getElementById("printableId").innerHTML);
        printHtml.document.write('</body></html>');
    
        printHtml.document.close(); 
        printHtml.focus(); = 10*/
    
        printHtml.print();
        printHtml.close();
    
        return true;
    
      }
Spectatress answered 27/7, 2021 at 12:1 Comment(1)
It doesn't retain the styling of the section which I am printing. Is there a fix for that?Castroprauxel
W
2

I tried many of the solutions provided.None of them worked perfectly. They either lose CSS or doesn't work in all browsers. I found a perfect and easy solution that neither losses CSS and work perfectly for all browsers.

Html

<div class="row" id="print-div">
      Your html 
    </div>

TYPESCRIPT

let popupWin = window.open('', '_blank', 'width=1080,height=595');
let printContents = document.getElementById("print-div").innerHTML;
let printHead = document.head.innerHTML;
popupWin.document
    .write(`<html>
     ${printHead}
    <body onload="window.print();">${printContents}</body></html>`);
popupWin.document.close();
Wedekind answered 15/2, 2022 at 11:5 Comment(0)
D
1

The printDiv() function came out a few times, but in that case, you loose all your binding elements and input values. So, my solution is to create a div for everything called "body_allin" and another one outside the first one called "body_print".

Then you call this function:

function printDiv(divName){

    var printContents = document.getElementById(divName).innerHTML;

    document.getElementById("body_print").innerHTML = printContents;

    document.getElementById("body_allin").style.display = "none";
    document.getElementById("body_print").style.display = "";

    window.print();

    document.getElementById("body_print").innerHTML = "";
    document.getElementById("body_allin").style.display = "";
    document.getElementById("body_print").style.display = "none";

}
Damal answered 27/2, 2014 at 17:47 Comment(1)
This line could be useful if you want unique id: printContents = printContents.replace(/id=("|')(.*?)("|')/g, 'id=$1$2_2$3');Damal
C
1

I tried many of the solutions provided.None of them worked perfectly. They either lose CSS or JavaScript bindings. I found a perfect and easy solution that neither losses CSS nor JavaScript bindings.

HTML:

<div id='printarea'>
    <p>This is a sample text for printing purpose.</p>
    <input type='button' id='btn' value='Print' onclick='printFunc();'>
</div>
<p>Do not print.</p>

Javascript:

function printFunc() {
    var divToPrint = document.getElementById('printarea');
    var htmlToPrint = '' +
        '<style type="text/css">' +
        'table th, table td {' +
        'border:1px solid #000;' +
        'padding;0.5em;' +
        '}' +
        '</style>';
    htmlToPrint += divToPrint.outerHTML;
    newWin = window.open("");
    newWin.document.write("<h3 align='center'>Print Page</h3>");
    newWin.document.write(htmlToPrint);
    newWin.print();
    newWin.close();
    }
Cassady answered 9/11, 2017 at 15:54 Comment(1)
This opening and creation of another window that does not work on Android. Only direct window.print() works.Febrile
W
1

Best css to fit space empty height:

@media print {
  body * {
    visibility: hidden;
    height:0;
  }
  #section-to-print, #section-to-print * {
    visibility: visible;
    height:auto;
  }
  #section-to-print {
    position: absolute;
    left: 0;
    top: 0;
  }
}
Words answered 19/4, 2018 at 8:20 Comment(0)
A
1

I'm very late to this party, but I'd like to pitch in with yet another approach. I wrote a tiny JavaScript module called PrintElements for dynamically printing parts of a webpage.

It works by iterating through selected node elements, and for each node, it traverses up the DOM tree until the BODY element. At each level, including the initial one (which is the to-be-printed node’s level), it attaches a marker class (pe-preserve-print) to the current node. Then attaches another marker class (pe-no-print) to all siblings of the current node, but only if there is no pe-preserve-print class on them. As a third act, it also attaches another class to preserved ancestor elements pe-preserve-ancestor.

A dead-simple supplementary print-only css will hide and show respective elements. Some benefits of this approach is that all styles are preserved, it does not open a new window, there is no need to move around a lot of DOM elements, and generally it is non-invasive with your original document.

See the demo, or read the related article for further details.

Alienage answered 10/3, 2019 at 19:7 Comment(0)
E
1

I found the solution.

@media print {
    .print-area {
        background-color: white;
        height: 100%;
        width: auto;
        position: absolute;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        z-index:1500;
        visibility: visible;
    }
    @page{
        size: portrait;
        margin: 1cm;
    }
/*IF print-area parent element is position:absolute*/
    .ui-dialog,
    .ui-dialog .ui-dialog-content{
        position:unset !important;
        visibility: hidden;
    }
}
Eustasius answered 25/9, 2019 at 4:55 Comment(0)
H
1

Elegant solution without css or window.open

export default function print(html: string) {
  const iframeElement = document.createElement('iframe');
  iframeElement.style.display = 'none';
  document.body.appendChild(iframeElement);

  const iframeDocument = iframeElement.contentDocument;
  iframeDocument.open();
  iframeDocument.write(html);
  iframeDocument.close();

  iframeElement.contentWindow.print();

  document.body.removeChild(iframeElement);
}
Hillell answered 10/10, 2023 at 9:45 Comment(0)
B
0

Use a special Stylesheet for printing

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

and then add a class i.e. "noprint" to every tag which's content you don't want to print.

In the CSS use

.noprint {
  display: none;
}
Basement answered 22/1, 2009 at 12:14 Comment(0)
C
0

With CSS 3 you could use the following:

body *:not(#printarea) {
    display: none;
}
Cardie answered 22/1, 2009 at 12:14 Comment(5)
Can't use that I'm afraid... (correct me if wrong) the page I'm working on is asp.net 1.1 / DHTMLLitha
It depends on the browser whether the :not() selector is already available or not.Cardie
Well then is my proposal just a look into the future … No, seriously. I just mentioned it for the sake of completeness. I know that it’s not practicable right now. Unfortunately.Cardie
You could use jQuery and this selector which (I think) would work in IE6 - $('body *:not(#printarea)').style('display', 'none');Undermine
this will hide all descendants of #printarea, since they are matched by *:not(#printarea). So basicly you end up with an empty container.Decorator
D
0

If you only want to print this div, you must use the instruction:

@media print{
    *{display:none;}
    #mydiv{display:block;}
}
Display answered 22/1, 2009 at 17:21 Comment(0)
R
0

You can use this: http://vikku.info/codesnippets/javascript/print-div-content-print-only-the-content-of-an-html-element-and-not-the-whole-document/

Or use visibility:visible and visibility:hidden css property together with @media print{}

'display:none' will hide all nested 'display:block'. That is not solution.

Ritch answered 5/4, 2013 at 13:21 Comment(0)
S
0

I had multiple images each with a button and needed to click on a button to print each div with an image. This solution works if I have disabled cache in my browser, and the image size doesn't change in Chrome:

        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;
    }

<div id="printableArea">
      <h1>Print me</h1>
</div>

<input type="button" onclick="printDiv('printableArea')" value="print a div!" />
Satiate answered 21/10, 2016 at 14:45 Comment(0)
G
0

Try this:

function printElement($elem){
    var $customPrintSection = document.getElementById('customPrintSection'),
        $customPrintSectionCss = document.getElementById('customPrintSectionCss');

    if ($customPrintSection){
        $customPrintSection.remove();
    }

    if ($customPrintSectionCss){
        $customPrintSectionCss.remove();
    }

    $customPrintSection = document.createElement('div');
    $customPrintSection.id = 'customPrintSection';

    $customPrintSectionCss = document.createElement('style');
    $customPrintSectionCss.id = 'customPrintSectionCss';

    document.body.appendChild($customPrintSection);
    document.body.appendChild($customPrintSectionCss);

    $customPrintSection.innerHTML = $elem.innerHTML;
    $customPrintSectionCss.innerHTML = '@media screen { div#customPrintSection { display: none; } } @media print { body *:not(div#customPrintSection):not(div#customPrintSection *) { display: none; } div#customPrintSection a[href]:after { content: none !important; } }';

    window.print();

    $customPrintSection.remove();
    $customPrintSectionCss.remove();
}

I like this solution because it doesn't affect the whole page, like a CSS-only solution, which in one particular answer makes all body elements invisible right off the bat. So good luck printing the whole page, if needed.

And I also prefer the "display: none" approach vs. the "visibility: hidden" one, so there's no need to make the printable element an absolute one and align it top-left. But I guess that's subjective.

And finally, it really beats the new window approach.

Given answered 29/11, 2022 at 13:41 Comment(0)
C
0

Combining the solutions from https://mcmap.net/q/42084/-print-lt-div-id-quot-printarea-quot-gt-lt-div-gt-only and https://mcmap.net/q/42084/-print-lt-div-id-quot-printarea-quot-gt-lt-div-gt-only, we arrive at a solution suitable for systems that utilize preprocessed CSS (such as Sass or SCSS) without losing component styles. This solution can be employed universally throughout code and isn't limited to specific IDs.

export function printById({ id }) {
    var printElement = document.getElementById(id);

    const originalStyle = JSON.parse(JSON.stringfy((document.body.style));
    const originalElement = JSON.parse(JSON.stringfy(printElement.style));

    document.body.style.visibility = 'hidden';
    printElement.style.visibility = 'visible';
    printElement.style.position = 'absolute';
    printElement.style.left = 0;
    printElement.style.top = 0;

    window.print();

    document.body.style = originalStyle;
    printElement.style = originalElement;
}
Cosgrove answered 13/4 at 6:19 Comment(0)
H
-1

base on @Kevin Florida answer, i made a way to avoid script on current page disable because of overwrite content. I use other file called "printScreen.php" (or .html). Wrap everything you want to print in a div "printSource". And with javascript, open a new window you created before ("printScreen.php") then grab content in "printSource" of top window.

Here is the code.

Main window :

echo "<div id='printSource'>";
//everything you want to print here
echo "</div>";

//add button or link to print
echo "<button id='btnPrint'>Print</button>";

<script>
  $("#btnPrint").click(function(){
    printDiv("printSource");
  });

  function printDiv(divName) {
   var printContents = document.getElementById(divName).innerHTML;
   var originalContents = document.body.innerHTML;
   w=window.open("printScreen.php", "_blank", "toolbar=yes,scrollbars=yes,resizable=yes,top=50,left=50,width=900,height=400");
   }
</script>

This is "printScreen.php" - other file to grab content to print

<head>
// write everything about style/script here (.css, .js)

</head>
<body id='mainBody'></body>
</html>


<script>
    //get everything you want to print from top window
    src = window.opener.document.getElementById("printSource").innerHTML;

    //paste to "mainBody"
    $("#mainBody").html(src);
    window.print();
    window.close();
</script>
Helminthic answered 16/1, 2020 at 1:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.