CSS media query for printing scrollable content

My ionic 2 project is used as a web app in addition to mobile (same code). In the web browser, I want to allow user to print some of the pages, and I’m having trouble getting the scrolling content to print. Only the first page wants to be printed. Below is what I have so far… hiding the headers, setting margins, etc, is working fine, but I can’t figure out how to get any scrolling content longer than one page. Any help would be appreciated. Thanks

(here is what I’ve tried, but the scrolling still isn’t working; it only prints the first page and cuts off the rest):

@media print {
  p a {
  word-wrap: break-word;
  }
  .scroll-content {
    position: relative;
    overflow:visible!important;
  }
  ion-header {
  display: none !important;
  }
    header nav, footer {
  display: none;
  }
  body {
   font: 12pt Georgia, "Times New Roman", Times, serif;
  line-height: 1.3;
  }
  h1 {
  font-size: 24pt;
  }
  h2 {
  font-size: 14pt;
  margin-top: 25px;
  }
  aside h2 {
  font-size: 18pt;
  }
}
2 Likes

To answer my own question… I’ve been banging on it for a while and finally have something that works (at least for my scenario). Any further suggestions/advice is still greatly appreciated.

The relevant lines to get all scrolling content instead of chopping it off at first page:

@media print {
body {
position: static;
overflow: initial;
}
ion-nav {
overflow: initial !important;
}
.scroll-content {
position: relative;
overflow:visible!important;
}
}

Here is my entire print media query for reference.

@media print {
body {
position: static;
overflow: initial;
}
ion-nav {
overflow: initial !important;
}
.scroll-content {
position: relative;
overflow:visible!important;
}
ion-header {
display: none !important;
}
header nav, footer {
display: none;
}
button {
display: none !important;
}
ion-fab {
display: none;
}
.pane {
position: initial;
}
p a {
word-wrap: break-word;
}
}

I would also like to point out this stackoverflow answer, for how to simulate print media in chrome dev tools… makes it simple to test:

Hi, thanks for posting your media query.

I’m trying it on ionic 2.0.0-final and printing still seems to be cut off on the first page. I’m wondering if it’s this media query still works for you on 2.0 or if you had to make any other modifications.

@sjalexandre I just checked and no it did not work on latest ionic. Based on a few minutes of dev tools inspection, I was able to make it work by adding the following contain setting to my print media query. I’m not sure what side effects this has, but it appears to work ok in my scenario. I welcome any suggestions for how to improve this.

@media print {
//...
  .app-root, .ion-page, ion-app, ion-nav, ion-tab, ion-tabs {
    contain: none;
  }

// more stuff here
}
1 Like

@randbrown Thank you! Worked great for me as well.

I can’t find a way to print my content inside an ion-content (at least 8 pages).

Any help, please?

@sjalexandre it did not work for me. Is there any updates on this?

@Corin have you figured it out?

Finally I’ve removed the ion-content and just used a div with my own class. Give it a try; :slight_smile:

1 Like

Could you please show me some code? I still can’t make it work.

I managed the problem with this code at app.css:

@media print{
  ion-header{ display: none !important; }  

  body, .app-root, .split-pane, .ion-page, ion-app, ion-nav { contain: none; }
  body, ion-nav{ overflow: initial; }
  body{ position: static; }

  [ion-content-print]{ overflow-y: visible !important; position: relative; }
}

and this template at my component:

<ion-header> ... </ion-header>
<section ion-content-print>
my printable content here
</section>

Here is my try for printing scrollable content in tabs panels:



@media print {
  ion-content {
    max-width: none;
  }
  ion-header, .tabbar {
    display: none !important;
  }

  body, .app-root, .split-pane, .ion-page, ion-app, ion-nav {
    contain: none;
  }
  body, ion-nav {
    overflow: initial;
  }
  body {
    position: static;
  }

  .scroll-content, .ion-page.show-page, .ion-page.show-page > ion-content, .app-root, ion-tabs, ion-tab {
    position: relative;
    height: auto;
    contain: none;
    overflow: visible;
  }

  .fixed-content, .scroll-content {
    margin-top: 0 !important;
  }
}

It may be smiplified but I don’t have time to play much with it. If you want to try, go ahead :slight_smile:

3 Likes

Thank you for this. It will save me a lot of time. I need to go back and make sure I understand it all, but it works.

Hi… thanks for sharing! One thing is, I have 3 tabs but i need to click them all before go to print… unless this will be empty… any idas how to load all tabs withou user clicking one by one?

This worked perfectly – thank you for this!!

@HugoHeneault, thanks for providing your sample style.

I’ve adapted the style provided by @HugoHeneault to better fit my applications. More specifically, I needed to support printing content that appears in a modal overlay (modal overlay to an active/shown page). It also supports non-modal content (arbitrary content in ion-content containers). I added some basic documentation as I tested and tweaked things.

The result is based on my observations; it may not work in all situations. Similarly, I tried to remove anything that wasn’t explicitly needed for my application.

The overall key when printing Ionic content is to override the height of content containers. When printing “height: 100%” refers to the height of a single page (as configured in the print dialog). The presence of “height: 100%” is effectively a death blow to spanning content to multiple pages.

Hope this variation can help someone! If you have questions, I can try to answer them.

// @media print styles are included to improve layout and content when printing in the web application.
@media print {
  // Within this print style, contain overrides are needed for reliable rendering in browsers that support it (Chrome).
  //  contain is set by Ionic for several components. Ionic sets contain based on assumptions about content (e.g. the
  //  size of child content cannot affect the height of the parent container. These assumptions no longer hold true
  //  for the CSS used during printing. If we do not set contain to none, the browser does not think the content
  //  can change, so it does not even consider rendering the new styles and layouts.

  // Certain content (e.g. headers and footers) are not useful in printed material. These objects also negatively affect
  //  the layout of certain content. In many cases they appear on top of the "main" content.
  ion-header, ion-backdrop, .tabbar, ion-footer {
    display: none !important;
  }

  // ion-nav needs to be treated special compared to the containers below. It is possible for an ion-nav to be present
  //  at a similar level to the container of the modal (ion-modal). If the position of ion-nav is set to relative it
  //  will always be displayed before the modal content. This causes the modal content to come after the ion-nav
  //  content, which is undesirable in all situations I've tested.
  ion-nav {
    contain: none;
    overflow: visible;
  }

  // When printing, we want to treat an active modal or page as  "full" content. We allow overflow and let the content
  //  determine the height of the container. We need to ensure the content as well as the content containers are
  //  updated. If a modal is active, the modal will be displayed in the printed content. Worth noting: using .app-root
  //  appears to cover ion-app, so ion-app is not included directly. Also, the items have been sorted based on scope.
  .scroll-content,
  ion-modal.show-page,
  ion-modal.show-page .modal-wrapper,
  ion-modal.show-page .ion-page.show-page,
  ion-modal.show-page .ion-page.show-page > ion-content,
  .ion-page.show-page,
  .ion-page.show-page > ion-content,
  ion-tab,
  ion-tabs,
  .app-root,
  body
  {
    contain: none;
    position: relative;
    height: auto;
    overflow: visible;
  }

  // When we are printing, we want to remove the default margin-top. The margin-top is needed so that scrollable content
  //  is not hidden under the nav bar at the top of the page. When printing, the nav bar is not included, so the margin
  //  is not needed.
  .fixed-content, .scroll-content {
    margin-top: 0 !important;
  }
}
1 Like

Thank you very much! It works perfectly for me.