{"id":204525,"date":"2015-07-14T07:40:14","date_gmt":"2015-07-14T14:40:14","guid":{"rendered":"http:\/\/css-tricks.com\/?p=204525"},"modified":"2015-07-14T10:38:49","modified_gmt":"2015-07-14T17:38:49","slug":"print-stylesheet-approaches-blacklist-vs-whitelist","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/print-stylesheet-approaches-blacklist-vs-whitelist\/","title":{"rendered":"Print Stylesheet Approaches: Blacklist vs Whitelist"},"content":{"rendered":"

The “blacklist” is a common approach to print stylesheets. We know that people probably don’t need to see our site navigation if they print out an article on our site. So we hide it from print like we would hide it from the screen (display: none;<\/code>). <\/p>\n

Is there a way to reverse that?<\/p>\n

<\/p>\n

The Blacklist Technique<\/h3>\n

You select all the elements on the page you don’t want printed, and put that into some CSS that is applied to the print media. Perhaps in a block at the bottom of your main stylesheet.<\/p>\n

@media print {\r\n  .main-navigation, .comments, .sidebar, .footer {\r\n     display: none;\r\n   }\r\n}<\/code><\/pre>\n

Alternatively, you could leave the job mostly the the HTML. You could create a “don’t print” class and apply it as needed.<\/p>\n

@media print {\r\n  .dont-print {\r\n    display: none;\r\n  }\r\n}<\/code><\/pre>\n
<section id=\"comments\" class=\"comments dont-print\">\r\n<\/section><\/code><\/pre>\n

Blacklisting is a common tactic, posted in print stylesheet tip articles all around the internet. <\/p>\n

The only trouble with it is that it requires maintenance.<\/strong> HTML changes, so you’ll need to maintain either your list of selectors to not print, or the classes in the HTML to be on the right elements. Easy to forget.<\/p>\n

The Whitelist Technique<\/h3>\n

Whitelisting would be the opposite technique. In your print styles, everything would be hidden from print except for elements you explicitly choose. <\/p>\n

Don’t get your hopes up too much though, it’s pretty tricky to pull off.<\/strong> My first thought was to universally hide things, then override with a class.<\/p>\n

\/* Bad idea #1 *\/\r\n@media print {\r\n  * {\r\n    display: none;\r\n  }\r\n  .print-me {\r\n    display: block;\r\n  }\r\n}<\/code><\/pre>\n
<main class=\"main-content print-me\">\r\n<\/main><\/code><\/pre>\n

There are two problems here:<\/p>\n

    \n
  1. The display<\/code> property isn’t inherited, so even though you told an element to show itself again, it’s child elements will still be hidden by the universal selector selecting and hiding them.<\/li>\n
  2. The parent elements of the element you told to show itself may still be hidden.<\/li>\n<\/ol>\n

    The latter of which we could maybe solve with…<\/p>\n

    \/* Bad idea #2 *\/\r\n@media print {\r\n  * {\r\n    display: none;\r\n  }\r\n  .print-me,\r\n  .print-me * {\r\n    display: block;\r\n  }\r\n}<\/code><\/pre>\n

    … selecting the child elements and having them show themselves again. But that would make all child elements block-level, which is bad. You don’t want your <a><\/code>, <em><\/code>, <strong><\/code>‘s and anything else that is inline<\/code>, inline-block<\/code>, inline-table<\/code>, inline-flex<\/code>, etc to become a block.<\/p>\n

    That would be harder to maintain than a blacklist.<\/p>\n

    I considered manually requiring all parent elements to also have “print-me” class, but that will expose sibling elements to being printed when they shouldn’t be (don’t have the class). I tried fixing that with a <\/p>\n

    \/* Bad idea #3 (addition to previous) *\/\r\n.print-me ~ *:not(.print-me) {\r\n  display: none;\r\n}<\/code><\/pre>\n

    But that doesn’t handle previous siblings.<\/p>\n

    This could be a pretty good use case for parent selectors in CSS, since you could potentially use a parent selector to un-hide a parent element if it contained an element with that specific class name. Theoretically something like *:contains(.print-me) { display: block; }<\/code>. <\/p>\n

    There may be a pure CSS solution to this yet. I admittedly didn’t spend hours and hours on this. There may be a clever tactic here I’m missing. I know that the visibility<\/a> property doesn’t inherit, so there may be potential there, but that doesn’t effect layout like you may want it to. I’m not sure :not()<\/code> was explored to its fullest potential here either.<\/p>\n

    If you want to play with ideas, here’s a test page for you.<\/a> It just has a button that toggles a class on the parent of a bunch of content, so you can pretend that class is like print styles and get it to do what you want.<\/p>\n

    My closest attempt<\/a> so far is a just give up and use JavaScript<\/strong> attempt. Using jQuery here for easy DOM traversal, the crux of it is automatically applying a class to all parents of an element ensuring they can be printed:<\/p>\n

    $(\".print-me\")\r\n  .parents()\r\n  .addClass(\"js-print-me\");<\/code><\/pre>\n

    Note I’m using a slightly different class name, so it’s not affected by the same rule that selects all descendants to display.<\/p>\n

    @media print {\r\n  * {\r\n    display: none;\r\n  }\r\n  .print-me,\r\n  .print-me * {\r\n    display: block;\r\n  }\r\n  .js-print-me {\r\n    display: block;\r\n  }\r\n}<\/code><\/pre>\n

    There are even sorta-kinda ways to detect a print event<\/a>, so you could apply\/remove a parent class name to get the page in this state when a user goes to print.<\/p>\n

    This doesn’t solve the inline-* problem though (where they go block-level instead of remaining what display value they used to be) which makes it fairly unusable. If you find JavaScript is an acceptable choice here, you could move the job of hiding to JavaScript as well, only applying display: none;<\/code> after saving what display type it already was<\/em>, so you could put it back when done. I think jQuery even kinda does this already somehow?<\/p>\n

    Rumor has it<\/a> there is some future CSS something-or-other that can handling toggling of visibility in a way that doesn’t tie it to layout (and that this is a pretty good use-case).<\/p>\n","protected":false},"excerpt":{"rendered":"

    The “blacklist” is a common approach to print stylesheets. We know that people probably don’t need to see our site navigation if they print out an article on our site. So we hide it from print like we would hide it from the screen (display: none;). Is there a way to reverse that?<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":248378,"url":"https:\/\/css-tricks.com\/totally-forgot-print-style-sheets\/","url_meta":{"origin":204525,"position":0},"title":"I totally forgot about print style sheets","date":"November 28, 2016","format":false,"excerpt":"Manuel Matuzovic rediscovers @media print {} styles. The first thing he shows in this article is a tweet by Aaron Gustafson in which Indiegogo's website is pretty jacked up for print. It basically looks like a site in which none of the CSS loads at all, which is probably because\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":580,"url":"https:\/\/css-tricks.com\/css-tricks-finally-gets-a-print-stylesheet\/","url_meta":{"origin":204525,"position":1},"title":"CSS-Tricks Finally Gets A Print Stylesheet","date":"March 3, 2008","format":false,"excerpt":"This is way past due...but it's finally here: a print stylesheet! I'll start by showing you the entire stylesheet, then I'll explain a little bit about what I was thinking. body { font-family: Georgia, serif; background: none; color: black; } #page { width: 100%; margin: 0; padding: 0; background: none;\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":32,"url":"https:\/\/css-tricks.com\/stylesheets-for-printing\/","url_meta":{"origin":204525,"position":2},"title":"Stylesheets for Printing","date":"August 3, 2007","format":false,"excerpt":"Jason from 37 Signals has a great post up on the Signal vs. Noise blog on how simple print stylesheets can be and still be effective. Basically using display: none; enmasse. People don't need your header or your footer or your navigation. If they are trying to print your webpage\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":167,"url":"https:\/\/css-tricks.com\/quick-tip-making-a-print-this-page-button\/","url_meta":{"origin":204525,"position":3},"title":"Quick Tip: Making a ‘Print This Page’ Button","date":"November 19, 2007","format":false,"excerpt":"Why bother? Most people know how to print a web page, so including a \"Print This Page\" button on a website is often overkill. But there are some circumstances where it really makes sense. I just came across one of those circumstances in some work I was doing for a\u2026","rel":"","context":"In "Article"","img":{"alt_text":"Coloring Page 1","src":"..\/..\/images\/coloring-page-1.gif","width":350,"height":200},"classes":[]},{"id":353225,"url":"https:\/\/css-tricks.com\/ct-css-performance-hints-via-injected-stylesheet-alone\/","url_meta":{"origin":204525,"position":4},"title":"ct.css \u2014 Performance Hints via Injected Stylesheet Alone","date":"October 5, 2021","format":false,"excerpt":"This is some bonafide CSS trickery from Harry that gives you some generic performance advice based on what it sees in your element. First, it's possible to make a