5

Context: making printable invoices to generate in a browser.

It's common in making printable webpages to use an @media print rule to change the way the content looks for a printed page. Ideally, because I'm printing only a small part of the page, I'd like to hide everything and then display the contents of a particular element.

Structure is something like this:

<body>
    <div id="topMenu">...lots of elements...</div>
    <div id="sideMenu">...lots more...</div>
    <div class="tools">...some tools...</div>
    <div class="printing">...some elements I want to print...</div>
    <div class="tools">...more stuff I don't want to print...</div>
</body>

Stuff I've tried:

Ideally, I'd like to do something like

body * {
    display: none;
}
.printing, .printing * { /* Both parts are needed to make it display */
    display: block !important;
}

But this won't work because some elements need to be inline and some need to be block. I've played with some different values for display from MDN and can't find one that easily resets the value to its original. display: initial seems to be treated like inline.

The suggestion in CSS: "display: auto;"? seems to only work for JS.

Of course, it is possible to explicity "hide" the stuff I don't want printed rather than display the stuff I do want, but it seems to me that it should be possible to go the other way.

In this question How to only show certain parts with CSS for Print? suggests body *:not(.printable *) {display:none;} but notes (as backed up on the w3 negation page ) that this is not yet supported.

I note that the w3 draft and the display-outside page seem to recommend using an unknown (to webkit) box-suppress property to preserve the display value while not displaying the element.

My questions:

What is the best way to hide everything and target certain elements for display when they don't all share a common display property?

What exactly does box-suppress do?

Community
  • 1
  • 1
Josiah
  • 3,008
  • 1
  • 34
  • 45
  • have you try with **less** – HoangHieu Oct 13 '14 at 17:55
  • 1
    To answer your auxiliary question, `box-suppress` is a possible future replacement for `display:none` that will hopefully make it easier to hide elements without worrying about changing its display type. I don't think it's currently supported so I'd stay away from it for now. More: http://www.w3.org/TR/css-display/ – Ky - Oct 14 '14 at 19:38
  • Thank you @Ben Leggiero. It appears to me based on reading the docs on `box-suppress` that this will make it possible to "toggle" display in the future rather than resetting it, which was my original approach, rather than building a specific selector. Will that be (a/the) use case for `box-suppress`? – Josiah Oct 14 '14 at 20:47
  • 1
    @Josiah it appears that's exactly the case! – Ky - Oct 16 '14 at 14:41
  • 1
    @BenLeggiero - imho, you should edit your answer to include that so people looking for future box-suppress information can find how to use it. Thanks for your help! – Josiah Oct 16 '14 at 14:51
  • @Josiah great point! I've added it – Ky - Oct 20 '14 at 18:29

3 Answers3

5

Since you specifically tagged this CSS3, try using CSS3!

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

This should work for the example you gave. I hope it works for your real-world application!


To answer your auxiliary question, as of October 2014, box-suppress is a possible future replacement for display:none that will hopefully make it easier to both hide and remove elements from the flow without worrying about changing its display type (as opposed to visibility still keeps it in the flow, and position:absolute which still keeps it visible). I don't think it's currently supported so I'd stay away from it for now. If you want to know more, see http://w3.org/TR/css-display

Ky -
  • 30,724
  • 51
  • 192
  • 308
1

You cannot use display for this purpose. See Display HTML child element when parent element is display:none

However, you can use visibility, as long as you use absolute positioning for the hidden content:

body, body * {
  visibility: hidden;
  position: absolute;
}

.printing, .printing * {
  visibility: visible;
  position: relative;
}
Community
  • 1
  • 1
Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79
0

If you don't use any absolute or fixed elements, you can use an alternative way of hiding elements.

Instead of using display: none to hide your elements, try using:

body * {
    position:absolute;
    top: -999999px;
    left: -999999px;
}

To set it back use:

.printing, .printing * {
     position: initial;
     /* OR */
     position: static;
}
quw
  • 2,844
  • 1
  • 26
  • 35
  • That could work. I have some absolutely positioned elements but I can probably rework that. – Josiah Oct 13 '14 at 18:07