What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Angular to identify the component or descendant you want, wait until its DOM is rendered, and then print either the current document with print-specific CSS or an isolated copy in a hidden iframe. JavaScript’s window.print() prints a document (not an element reference), so “print this element” means controlling what is visible in the print document or creating a separate print document.

Choose the element you actually want to print

Every Angular component has a host element: the element whose tag matches the component selector. The component’s template is rendered inside that host. If the whole component is the print unit, use the host. If only part of it should print, query a descendant such as a card, invoice, or report panel.

<app-invoice>
  <section class="invoice-sheet">...</section>
</app-invoice>

In this example, <app-invoice> is the host and .invoice-sheet is a descendant target. Prefer a stable class, template reference, or ID over a selector that depends on generated classes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for Angular’s rendered DOM

DOM-dependent work should run in a render callback. Angular does not guarantee that a component DOM is fully rendered outside render callbacks. Use afterNextRender for one-time setup or capture preparation; use afterEveryRender only when you genuinely need to react after every render. These callbacks do not run during server-side rendering or build-time prerendering, so browser printing must remain on the client.

import { Component, ElementRef, inject, afterNextRender } from '@angular/core';

@Component({
  selector: 'app-invoice',
  standalone: true,
  template: `
    <section class="invoice-sheet" id="invoice-to-print">
      <h1>Invoice #1042</h1>
      <ng-content></ng-content>
    </section>
    <button type="button" (click)="print()">Print invoice</button>
  `
})
export class InvoiceComponent {
  private readonly host = inject(ElementRef<HTMLElement>);
  private target!: HTMLElement;

  constructor() {
    afterNextRender(() => {
      this.target = this.host.nativeElement.querySelector('#invoice-to-print')!;
    });
  }

  print(): void {
    if (!this.target) return; // Render callback has not completed yet.
    window.print();
  }
}

Keep the actual print call on an intentional user action where possible. Before calling it, make sure asynchronous data, images, web fonts, and any loading indicators have reached their final state.

Method 1: Print the current document with CSS

This is normally the simplest and most robust approach because it preserves the page’s existing styles, fonts, images, and Angular-rendered content. Hide everything except the target when the browser enters print media.

/* invoice.component.css or a global stylesheet */
@media print {
  body * {
    visibility: hidden;
  }

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

  #invoice-to-print {
    position: absolute;
    inset: 0;
    width: 100%;
  }

  .no-print {
    display: none !important;
  }
}

@page {
  size: A4 portrait;
  margin: 12mm;
}

visibility keeps the target’s layout descendants available while hiding unrelated content. For unrelated controls that do not provide a required layout ancestor, display: none can reduce empty space instead. Test either choice with your actual component: fixed-height wrappers, overflow clipping, transforms, and positioned ancestors can otherwise truncate or shift the result.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use @page for paper size, orientation, and margins. Print styles still follow CSS cascade and specificity, so a more specific application rule may override your print rule; inspect the computed styles in the browser’s print preview. Long content should be tested over several page breaks, including tables, headings, and images.

Component and global style scope

With Angular’s default emulated encapsulation, component styles receive scoped attributes. A rule in the component stylesheet can therefore work for elements in that component, but global page elements may need global styles. Shadow DOM encapsulation creates a stronger boundary: selectors outside the shadow root cannot reveal its internals. Put the print rules in the appropriate scope and verify them in preview.

Method 2: Copy the element into a print iframe

Use an isolated document when hiding the current page is unsafe, when the print view needs different markup, or when you want a dedicated print layout. A copied element does not automatically bring its styles, fonts, images, or scripts with it, so include the assets required by the print view.

printIsolated(): void {
  const target = this.host.nativeElement.querySelector('#invoice-to-print');
  if (!target) return;

  const frame = document.createElement('iframe');
  frame.style.position = 'fixed';
  frame.style.right = '0';
  frame.style.bottom = '0';
  frame.style.width = '0';
  frame.style.height = '0';
  frame.style.border = '0';
  frame.setAttribute('aria-hidden', 'true');
  document.body.appendChild(frame);

  const printDocument = frame.contentDocument!;
  printDocument.open();
  printDocument.write(`
    <!doctype html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Invoice #1042</title>
        <link rel="stylesheet" href="/styles.css">
        <style>
          @page { size: A4 portrait; margin: 12mm; }
          body { font-family: Arial, sans-serif; }
        </style>
      </head>
      <body></body>
    </html>`);
  printDocument.close();

  printDocument.body.appendChild(target.cloneNode(true));

  const printWindow = frame.contentWindow!;
  const removeFrame = () => {
    frame.remove();
  };
  printWindow.addEventListener('afterprint', removeFrame, { once: true });

  // Wait for the iframe's resources before opening the dialog.
  const printWhenReady = () => {
    printWindow.focus();
    printWindow.print();
    // Fallback for browsers that do not fire afterprint reliably.
    setTimeout(removeFrame, 60_000);
  };

  if (printDocument.fonts) {
    printDocument.fonts.ready.then(printWhenReady);
  } else {
    printWhenReady();
  }
}

For images, wait for each image’s decode() promise where supported, or check image.complete and naturalWidth. If the target uses relative URLs, ensure the iframe document has a suitable base URL or absolute asset URLs. Do not copy an element whose content depends on event handlers unless the print copy only needs its rendered markup.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Printing behavior you cannot override

  • window.print() opens the browser’s print dialog for the window on which it is called; it accepts no DOM element argument.
  • If printing is requested while a document is loading, the browser waits for loading to finish.
  • The call blocks JavaScript while the dialog is open in browsers that implement it that way.
  • The user or browser settings choose the final printer or PDF destination and can control options such as background graphics and scale.

Your application can prepare markup and CSS, but it cannot guarantee identical pagination across every browser, operating system, printer, or PDF driver. Validate the browsers and Angular configurations your application supports, especially for long documents, images, web fonts, and Shadow DOM.

Which approach should you use?

Criterion Current-document print CSS Dedicated iframe
Implementation effort Usually lower Higher: copy markup and load assets
Existing global and component styles Retained automatically Must be copied or recreated
Isolation from application UI Achieved with selectors and print rules Strong isolation in a separate document
Shadow DOM considerations Rules must be inside the relevant shadow root Serialized shadow content and styles require explicit handling
Custom pagination and print-only markup Possible, but constrained by the page layout Convenient for a purpose-built print view

Start with print CSS. Move to an iframe when the page contains complex application chrome, conflicting styles, or a print representation that should not share the live layout.

Common failures and fixes

The whole page prints

Check that the target selector matches the rendered element, that the print rule is loaded, and that no more-specific rule restores visibility or display. Use the browser’s print preview and computed-style inspector.

The target is blank or missing

The query may run before Angular has rendered, or it may target the host when the desired content is a descendant. Move the query into afterNextRender, verify the selector, and guard against a null result.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Content is clipped

Inspect ancestors for overflow: hidden, fixed heights, scroll containers, transforms, and positioning contexts. Override those constraints in @media print and test a document longer than one page.

Styles disappear in the iframe

Clone only the markup you need, then load the same stylesheet and font resources in the iframe. Relative URLs, content-security policies, and cross-origin font restrictions can prevent assets from loading.

Images or fonts are absent

Wait for image decoding and document.fonts.ready before calling print(). Ensure the resources are reachable from the print document and that the user has not disabled background graphics when those graphics are essential.

Server-side rendering throws an error

Do not access window, document, or ElementRef.nativeElement in server execution. Put browser-only setup in afterNextRender and invoke printing only from a client-side event.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The dialog opens before data is ready

Disable the print control until the observable or signal supplying the target is complete. If images arrive afterward, wait for them explicitly rather than relying on a fixed delay.

Iframe cleanup never happens

Listen for afterprint, but also use a conservative timeout fallback because event behavior differs between browsers. Remove the iframe after printing so repeated prints do not accumulate hidden documents.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your real goal is a screenshot or PDF of a URL rather than an interactive, user-initiated print dialog, ScreenshotNeo provides a website screenshot API and MCP server. It can capture a rendered page, element, or PDF without you maintaining a browser-print pipeline. Cookie and consent banners are accepted and removed before capture, along with more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the complete parameter list and output details in the ScreenshotNeo documentation. The same request from Python:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

And Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. These captures are for a URL; an Angular app must be deployed and reachable, and authenticated or stateful pages may require custom headers or cookies.

Sign up free for ScreenshotNeo to get 1,000 screenshots a month without a card.

Practical validation checklist

  • Confirm the selector identifies the intended host or descendant after rendering.
  • Open print preview with data, images, fonts, and long content present.
  • Check page size, margins, orientation, headers, footers, and page breaks.
  • Test both emulated encapsulation and Shadow DOM if the application supports them.
  • Repeat on each supported browser, operating system, and PDF destination.
  • For iframe printing, verify styles, fonts, image URLs, cleanup, and repeated-print behavior.

Frequently Asked Questions

Can I pass an Angular element directly to window.print()?

No. window.print() has no element parameter. Restrict the current document with print CSS or print a separate iframe document.

Should I use afterNextRender or afterEveryRender?

Use afterNextRender for a one-time DOM lookup or setup. Use afterEveryRender only when work must run after every Angular render, and avoid unnecessary repeated printing work.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Does an iframe automatically include the component’s Angular styles?

No. An iframe has its own document. Load the required styles and assets explicitly, then wait for them before calling its window.print().

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.