43

I have a page with lots of data, tables and content. I want to make a print version that will only display very few selected things.

Instead of writing another page just for printing, I was reading about CSS's feature for "@media print".

First, what browsers support it? Since this is an internal feature, it's OK if only the latest browsers support it.

I was thinking of tagging a few DOM elements with a "printable" class, and basically apply "display:none" to everything except those elements with the "printable" class. Is that doable?

How do I achieve this?

EDIT: This is what I have so far:

<style type="text/css">
@media print {
    * {display:none;}
    .printable, .printable > * {display:block;}
}
</style>

But it hides everything. How do I make those "printable" elements visible?

EDIT: Trying now the negative approach

<style type="text/css">
@media print {
    body *:not(.printable *) {display:none;}
}
</style>

This looks good in theory, however it doesn't work. Maybe "not" doesn't support advanced css ...

Nathan H
  • 48,033
  • 60
  • 165
  • 247
  • I think you should approach it from the other side. HIDE content that is not to be printed, as opposed to hiding everything and only showing the bits you want printed. Because it's not really possible to achieve in CSS in a clean way. – Strelok Aug 12 '10 at 00:34
  • It is actually possible do it in the way @Strelok suggest: you can mark all elements that should not be included in the print as no-print, avoiding to mark a container of the elements you actually want to. .no-print{display: none:} But it is really dumb. The way you want to do it is cleaner and clever. But sad, this seems to be the only way. Hope it is not. What you want to do is a good use case for a parent css selector: https://css-tricks.com/parent-selectors-in-css/ You could say: * {display:none;} .printable, .printable < * {display: block} Sad that selector doesn't exists. – jgomo3 Aug 01 '15 at 03:53
  • The problem is that this still applies the `display: none` style to the **parent** of the `.printable` block. Therefore, the `.printable` block and all it children will not be displayed because their parents aren't. – lolgab123 Dec 02 '22 at 21:50

7 Answers7

21

If you want to display some links etc. when in the browser, that you don't want to be printed. Furthermore you have some logos and letterhead info that only should go on the printed page. This seems to work fine:

Example:

CSS:

@media print {
  .noPrint {
      display:none;
  }
}
@media screen {
   .onlyPrint {
       display: none;
   }
}

HTML:

<div class="noPrint" id="this_is_not_printed"  >
   <a href=links.html>
</div>
<div class="onlyPrint"  id="this_is_only_seen_on_printer" >
   <img scr=logo.png >
   <img scr=letterhead.png >
</div>
jp06
  • 185
  • 3
  • 8
oleviolin
  • 894
  • 10
  • 10
  • To use both `@media print` and `@media screen` solved it for me. Thx. – Dirk Mar 21 '19 at 15:22
  • "onlyPrint" elements will be available for screen readers. I believe it should be done like this: @media only speech, only screen { .onlyPrint { display: none; } } – Vincente Dec 02 '21 at 11:29
19

Start here. But basically what you are thinking is the correct approach.

Thanks, Now my question is actually becoming: How do I apply CSS to a class AND ALL OF ITS DESCENDANT ELEMENTS? So that I can apply "display:block" to whatever is in the "printable" zones.

If an element is set to display:none; all its children will be hidden as well. But in any case. If you want a style to apply to all children of something else, you do the following:

.printable * {
   display: block;
}

That would apply the style to all children of the "printable" zone.

Strelok
  • 50,229
  • 9
  • 102
  • 115
  • 5
    Thanks that's almost perfect! Now the only issue is that not ALL elements should be "block". As I am testing, I realize that divs are "block", regular stuff is "inline", tables are "table", tbody are "table-row-group", tr are "table-row", etc ... I could add rules for each individually, but is there a way to just say "apply the regular browser styles"? – Nathan H Aug 12 '10 at 00:41
15

A simple way:

<style>
    .print-only{
        display: none;
    }

    @media print {
        .no-print {
            display: none;
        }

        .print-only{
            display: block;
        }
}
</style>
jhpratt
  • 6,841
  • 16
  • 40
  • 50
Polle
  • 159
  • 1
  • 2
  • 3
    This is correct, but it could cause unnecessary breaks in your formatting if the .print-only element is naturally inline (for example) instead of block. – Brett Pennings Sep 22 '16 at 13:58
  • 1
    I think 'diaply:block' will ruins some elements that has another display type. – pixparker Sep 12 '17 at 05:50
5

I got here because I was curious about printing a chart generated by chart.js. I wanted to just print the chart directly from the page (with a button that does a 'window.print') without all of the other content of the page.

So, I got closer by using the technique from the answer here: Why can't I override display property applied via an asterisk? .

You have to apply the 'asterisk' to the 'body' element, not just by itself. So, using the example CSS that the OP (Nathan) added to the question, I changed it to this:

<style type="text/css">
@media print {
    body * {display:none;}
    .printable, .printable > * {
    display: block !important;
  }
}
</style>

Then adding that 'printable' class to the chart itself, as in

<canvas id="myChart" class="printable" width="400" height="400"></canvas>

Which removed all page elements on the printed output except the chart when the 'print' button is clicked (via this):

<script>
    myChart.render();
    document.getElementById("printChart").addEventListener("click",function(){
        window.print();
    });     
</script>

So, perhaps this will help anyone that gets to this question via the googles.

Rick Hellewell
  • 1,032
  • 11
  • 34
  • this hides all the elements but doesn't display block to all the elements and its children with that. I have the exact same css – NewBie1234 Apr 17 '19 at 12:40
  • 1
    This is an older answer, and that code worked when I used it back in 2017. Should still work. The script is a separate button that has an ID of 'printChart'; that code is not shown in my answer. The asterisk in the 4th line of the CSS should let any child elements of 'printable' class be printable, I believe. (There was a missing closing style command in my answer; I added it just now.) – Rick Hellewell Apr 18 '19 at 00:16
  • thats ok, I figured it shouldn't have changed that much. What I have right now is pretty similar, I click a button that triggers the window.print functionality. The only thing is that when I look at the page, its blank. I'm working with ASP.Net, its an old application and might not work as good as. Thanks for the reply! – NewBie1234 Apr 18 '19 at 13:24
  • I just noticed the blank page after print preview on another site of mine that uses the CSS code above. Using latest FF/Win10. Not sure why it happens. If I take away that CSS, Print Preview works properly. Puzzling. – Rick Hellewell Sep 17 '19 at 21:58
4

Came across the same question recently and for me, this solution works just perfect:

@media print {

    * {
        visibility: hidden;
    }

    .printable {
        visibility: visible;
        position: absolute;
        top: 0;
        left: 0;
        padding: 10mm;
    }

    .printable * {
        visibility: visible;
    }
}

Since visibility: hidden doesn't remove elements, as display: none does, it is possible to change it for desired elements separately.

Yaroslav
  • 205
  • 3
  • 7
  • The problem with that is that `hidden` elements still take their space in the document. Therefore you end up with white patches in the document to print... – lolgab123 Dec 02 '22 at 21:48
3

Nearly all browsers support it. It might be advantageous to use the media attribute on the link tag.

Using display: none; in some of your rules would be an appropriate way to handle your situation.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • 1
    Thanks, Now my question is actually becoming: How do I apply CSS to a class AND ALL OF ITS DESCENDANT ELEMENTS? So that I can apply "display:block" to whatever is in the "printable" zones. – Nathan H Aug 12 '10 at 00:14
3

I suggest to hide the element that you won't print:

HTML

<h1 class="no-print" >Welcome Just Screen</h1>
<div> I want print this section :)</div>
<div class="no-print">It's display only on screen</div>

CSS

@media print {     
    .no-print {
        display: none;
    }
}
tschwab
  • 1,056
  • 1
  • 12
  • 27
pixparker
  • 2,903
  • 26
  • 23