PDFObject

An open-source standards-friendly JavaScript utility for embedding PDF files into HTML documents.

The PDFObject utility is © 2008-2021 Philip Hutchison. Released with an MIT license.

1. Create a container to hold your PDF

<div id="example1"></div>

2. Tell PDFObject which PDF to embed, and where to embed it

<script src="/js/pdfobject.js"></script>
<script>PDFObject.embed("/pdf/sample-3pp.pdf", "#example1");</script>

3. You can optionally use CSS to change the appearance of the containing element, such as height, width, border, margins, etc.

<style>
.pdfobject-container { height: 30rem; border: 1rem solid rgba(0,0,0,.1); }
</style>

Question: Is JavaScript required for embedding PDFs in your HTML page?

Answer: No.

In fact, here are some examples for embedding PDFs in your web page using pure HTML markup without JavaScript, if you'd rather go that route.

Why use PDFObject?

  • PDFObject detects browser support for inline/embedded PDFs. (In case you were wondering, your browser embedded PDFs. )

    If you're working with dynamic HTML, such as a single-page web app, you may need to insert PDFs on-the-fly. However, PDF embedding is not supported by certain browsers. If you insert markup without first checking for PDF support, you could wind up with missing content or a broken UI.

    The PDFObject utility helps you avoid these situations by detecting support for PDF embedding in the browser; if embedding is supported, the PDF is embedded. If embedding is NOT supported by the browser, the PDF will NOT be embedded.

  • By default, PDFObject inserts a fallback link to the PDF when the browser does not support inline PDFs. This ensures your users always have access to your PDF, and is designed to help you write less code. The fallback link can be customized, or the option can be disabled if you prefer.

  • PDFObject is npm-ready. Modern web apps use npm to manage packages and dependencies. PDFObject 2.x is registered with Node Package Manager (npm) and can be loaded dynamically.

  • PDFObject also makes it easy to specify Adobe's proprietary "PDF Open Parameters". Be warned these parameters are only supported by Adobe Reader, most PDF readers will ignore the parameters, including the built-in PDF readers in Chrome, Edge, Internet Explorer, and Safari. Read more below.

What PDFObject doesn't do

  • PDFObject is not a rendering engine. PDFObject just writes an <embed> element to the page, and relies on the browser or browser plugins to render the PDF. If the browser does not support embedded PDFs, PDFObject is not capable of forcing the browser to render the PDF.

    If you need to force browsers to display a PDF, we suggest using Mozilla's PDF.js. Note that PDF.js is subject to its own limitations, such as cross-domain security restrictions. PDFObject and PDF.js play well together, there are links to some great PDF.js examples in the Examples section below.

  • PDFObject does not provide the ability to customize the look and feel of the PDF toolbar. The toolbar is controlled by the browser, and will vary widely from browser to browser (Chrome versus Safari versus Firefox, etc.). Some of these browsers provide the ability to show or hide the toolbar, or a feature such as the search field, via PDF Open Parmeters. However, in general the browsers do NOT provide any mechanism for customizing the toolbar. If you really need to customize the toolbar, try forking Mozilla's PDF.js and customizing it to suit your needs.

  • PDFObject does not validate the existence of the PDF, or that the PDF is actually rendered. The assumption is that you are specifying a valid URL and the network is functioning normally. PDFObject does not check for 404 errors, and JavaScript cannot detect whether the PDF actually renders, unless you are using PDF.js, which is outside the scope of PDFObject.

  • PDFObject does not magically implement PDF Open Parameters. As mentioned above, these parameters are not widely supported. The PDF rendering engine either supports them or doesn't — PDFObject cannot force the rendering engine to implement these features.

Back to top

Browser Support

PDFObject 2.x is designed for modern browsers, and has been successfully tested in Chrome, Firefox, Safari, IE 11, and MS Edge. Mobile browsers do not support PDF embedding! For mobile browsers (Android, iOS, iPadOS), PDFObject will load your specified fallback content. If you find issues or would like to share your own testing results, please post an issue in GitHub.

IMPORTANT: Browser support for PDFObject does not mean the browser supports PDF embedding! The reason PDFObject exists is to help you embed PDFs when the browser supports PDFs, and to display alternative non-PDF content when the browser doesn't support PDFs. While most modern desktop browsers support PDF embedding, some do not. Most notably, Internet Explorer 11 requires a 3rd-party tool such as Adobe Acrobat for displaying PDFs.

Back to top

API

PDFObject provides two properties and one method.

PDFObject.supportsPDFs [property]

Returns true or false based on detection of navigator.mimeTypes['application/pdf'] and/or ActiveX AcroPDF.PDF or PDF.PdfCtrl.

Will return false for all mobile browsers. With the advent of assumptionMode in 2.1 and greater, PDFObject.supportsPDFs now returns true for all modern desktop browsers.

PDFObject does not perform detection for specific vendors (Adobe Reader, FoxIt, PDF.js, etc.). Note: For those who wish to target PDF.js, there is an option in PDFObject.embed() to force use of PDF.js. Read below for more details.

if(PDFObject.supportsPDFs){
   console.log("Yay, this browser supports inline PDFs.");
} else {
   console.log("Boo, inline PDFs are not supported by this browser");
}

Demo: Detection of PDF support

PDFObject.pdfobjectversion [property]

Returns the version of PDFObject.

console.log(PDFObject.pdfobjectversion); //"2.2.0"

PDFObject.embed(url [string], target [mixed], options [object]) [method]

Returns the embedded element (<embed> or <iframe> depending on situation), or false if unable to embed.

See Examples for specific code examples and functioning demos.

//embeds a PDF and makes it fill the browser window
PDFObject.embed("myfile.pdf");
//embeds a PDF into the element "my-container" with no extra options specified
PDFObject.embed("myfile.pdf", "#my-container");
//embeds a PDF into the element "my-container" with a few options specified
var options = {
    height: "400px",
    pdfOpenParams: { view: 'FitV', page: '2' }
};
PDFObject.embed("myfile.pdf", "#my-container", options); 

 

Specifying a target HTML node

The target parameter can accept a CSS selector, HTML node, or jQuery object.

//passes a CSS selector to specify the target
PDFObject.embed("myfile.pdf", "#my-container");
//passes a vanilla HTML node for target
var mynode = document.getElementById("someID");
PDFObject.embed("myfile.pdf", mynode);
//passes a jQuery object (HTML node) for target
var $node = $("#someID");
PDFObject.embed("myfile.pdf", $node);

 

Options

The options parameter provides a lot of flexibility.

  • assumptionMode [boolean]. Default: true

    Older browsers require third-party plugins such as Adobe Reader for displaying PDFs. Most newer 'modern' browsers provide PDF support natively, and no longer require plugins. When PDFObject's assumptionMode is set to true, PDFObject will check to see if the browser is considered modern. If yes, PDFObject will assume PDF support is available, will bypass its normal PDF support detection, and will write the PDF embed code to the page. Browsers that are not considered modern will fall back to the default PDFObject behavior — a check will be performed to see if PDF embedding is supported before attempting to insert the PDF embed code. If PDF support is detected, the embed will proceed. If not, the normal fallback behavior will apply.

    Flowchart of logic for assumptionMode

    assumptionMode is a direct response to Mozilla's decision to remove navigator.mimeTypes support in Firefox. Mozilla is attempting to make Firefox more secure by reducing opportunities for browser fingerprinting. Plugin inspection is a core component of many browser fingerprinting techniques. However, many well-intentioned scripts such as PDFObject query navigator.mimeTypes to determine whether specific media, such as PDFs (navigator.mimeTypes['application/pdf']), Flash SWFs, and specific audio or video codecs are supported.

  • customAttribute [object]. Default: null

    This option allows developers to specify a custom attribute on the embed and iframe elements. For example, you could specify the loading attribute on the iframe to be "lazy".

    Values must be set as key and value, as shown in the following example:

    var options = {
        customAttribute: { key: "foo", value: "bar" }
    };
    PDFObject.embed("myfile.pdf", "#my-container", options);
    

    See a custom attribute example in action.

  • forceIframe [boolean]. Default: false

    If this boolean is set to true, and PDF embedding is supported by the browser, PDFObject will write an <iframe> to the page instead of an <embed>.

  • forcePDFJS [boolean]. Default: false

    If this boolean is set to true and the PDFJS_URL string is not null, PDFObject will attempt to use PDF.js to embed the PDF in the browser, regardless of the browser's default PDF viewer.

  • height [string]. Default: "100%"

    Will insert the height as an inline style via the style attribute on the the generated element (<embed> or <iframe> depending on situation). If left unspecified, PDFObject will default to 100%. Is standard CSS, supports all units, including px, %, em, and rem.

    If you would like PDFObject to omit all inline styles, set the omitInlineStyles option to true.

    Tip: It's safer to specify dimensions using non-inline CSS instead of this inline code. See "Specifying dimensions" below.

    PDFObject.embed("myfile.pdf", "#my-container", {height: "20rem"});
    //outputs <embed src="myfile.pdf" style="height:20rem;">
  • id [string]. Default: null

    Any string entered here will be appended to the generated <embed> or <iframe> element as the ID. If left unspecified, no ID will be appended.

    PDFObject.embed("myfile.pdf", "#my-container", {id: "myID"});
    //outputs <embed src="myfile.pdf" id="myID">
  • omitInlineStyles [boolean]. Default: false

    If this boolean is set to true, PDFObject will not include any inline styles when generating the <embed> or <iframe> elements.

    Warning: If you do not specify your own styles, especially sizing, via CSS, the PDF may render incorrectly or be invisible.

  • page [string or number]. Default: null

    Alias for PDF Open Parameters "page" option. Any number entered here will cause the PDF be opened to the specified page number, if the browser supports it. If left unspecified, the PDF will open on page 1.

    PDFObject.embed("myfile.pdf", "#my-container", {page: "2"});
  • PDFJS_URL [string]. Default: null

    If you would like to use PDF.js with PDFObject, you will need to specify the URL of the PDF.js viewer HTML file. PDFObject will automatically append the required querystring to the PDF.js viewer HTML file URL. See the Examples section below for a functioning demo.

  • pdfOpenParams [object]. Default: null

    Allows you to specify Adobe's PDF Open Parameters.

    Warning: These are proprietary and not well supported outside of Adobe products. Most PDF readers support the page parameter, but not much else. PDF.js supports page, zoom, nameddest, and pagemode.

    • page is the most widely-supported PDF Open Parameter outside of Adobe products.
      PDFObject.embed("myfile.pdf", "#my-container", {pdfOpenParams: { page: 10 }});
      //If supported, will cause the PDF viewer to load
      //the PDF and automatically scroll to page 10
      Note that PDFObject provides a convenient alias for page so you don't need to use the pdfOpenParams child object. All other PDF Open Parameters need to be listed as children of the pdfOpenParams object, as illustrated above.
      PDFObject.embed("myfile.pdf", "#my-container", { page: 10 });
      //If supported, will cause the PDF viewer to load
      //the PDF and automatically scroll to page 10
    • Learn more about Adobe's PDF Open Parameters
    • Learn more about PDF.js's implementation of PDF Open Parameters
  • supportRedirect [boolean]. Default: false

    On macOS systems, Safari does not properly embed PDFs that have been requested via 302 URL redirection when embedding using the <embed> element. Setting supportRedirect to true forces PDFObject to use an <iframe> instead of an <embed> for desktop Safari.

    Hat tip to John Hunter for the discovery and fix.

  • suppressConsole [boolean]. Default: false

    If this boolean is set to true, PDFObject not write any error messages to the browser's console.

  • width [string]. Default: "100%"

    Will insert the width as an inline style via the style attribute on the generated element (<embed> or <iframe> depending on situation). If left unspecified, PDFObject will default to 100%. Is standard CSS, supports all units, including px, %, em, and rem.

    If you would like PDFObject to omit all inline styles, set the omitInlineStyles option to true.

    Tip: It's safer to specify dimensions using non-inline CSS instead of this inline code. See "Specifying dimensions" below.

    PDFObject.embed("myfile.pdf", "#my-container", {width: "500px"});
    //outputs <embed src="myfile.pdf" style="width:500px;">

Back to top

Common Use Cases

Here are some of the most common use cases for PDFObject. See the Examples section below for more examples.

Default behavior: the full-browser embed

If you don't specify a target element, PDFObject will default to document.body, which will cause the PDF to fill the entire browser window.

The following two examples have identical functionality.

PDFObject.embed("/pdf/sample-3pp.pdf");

Demo: Full-browser embed (no selector specified)

PDFObject.embed("/pdf/sample-3pp.pdf", document.body);

Demo: Full-browser embed (explicit selector)

Embedding in a sized container

By default, PDFObject generates an <embed> element with a width and height of 100%. It will automatically fill the target container.

PDFObject.embed("myfile.pdf", "#my-container");
//outputs <embed src="myfile.pdf" style="width:100%;height:100%">

PDFObject allows you to specify dimensions via the options parameter. These dimensions will be appended directly to the <embed> element, as shown here.

var options = {
   width: "20rem",
   height: "20rem"
};
PDFObject.embed("myfile.pdf", "#my-container", options);
//outputs <embed src="myfile.pdf" style="width:20rem;height:20rem">

If you specify dimensions on the <embed> element directly, you will lose the ability to resize the element via CSS, because the inline styles will always take precedence over the other styles in your file. Therefore it is recommended that you specify dimensions using external CSS rules, as shown here.

Note: PDFObject automatically appends the class pdfobject to the <embed> element, and pdfobject-container to the target element. This helps you target your element in CSS.

In this example, the dimensions of the target element are only specified if the PDF has been embedded (via the pdfobject-container class).

<style>
/* Only resize the element if PDF is embedded */
.pdfobject-container {
   width: 200px;
   height: 500px;
}
</style>

<div id="my-container"></div>

<script>
PDFObject.embed("myfile.pdf", "#my-container");
</script>

Demo: Embed a PDF and specify dimensions using CSS

Page number specified

As previously mentioned, most PDF Open Parameters are not widely supported. However, there is one parameter that enjoys wide support: the page parameter.

If you specify a page number using the page parameter, as shown in this example, the PDF will auto-scroll to the specified page number.

var options = {
page: "2"
};
PDFObject.embed("/pdf/sample-3pp.pdf", "#my-container", options);

Additional PDF Open Parameters specified

As previously mentioned, most PDF Open Parameters are not widely supported. However, there is one parameter that enjoys wide support: the page parameter.

If you specify a page number using the page parameter, as shown in this example, the PDF will auto-scroll to the specified page number.

var options = {
    height: "400px",
    page: '2',
    pdfOpenParams: {
        view: 'FitV',
        pagemode: 'thumbs',
        search: 'lorem ipsum'
    }
};

PDFObject.embed("/pdf/sample-3pp.pdf", "#my-container", options);

Demo: Specifying PDF URL containing querystring, with PDF Open Parameters

Back to top

Examples

The following links demonstrate the many ways PDFObject can be utilized.

Back to top

Changelog

A big thank you to everyone who submitted issues in GitHub and helped test PDFObject.

  • 2.2.12, June 2023: Refactored one line of code to restore IE11 compatibility, per #287
  • 2.2.11, May 2023: Typo in version number within PDFObject code. Yup, I'm a bit rusty.
  • 2.2.10, May 2023: Version bump for cleaning up docs and aligning on NPM. I'm a bit rusty.
  • 2.2.9, May 2023:
    • Fixed regression for pdfOpenParams handling, resolves issue #272. Hat tip to Theo Beers.
    • Added ability to specify custom attribute on embed and iframe elements, per #274
  • 2.2.8, April 2022:
    • Refactored to reduce redundant code. Simplified iframe and PDFJS handling. Subsequently resolves #263 (double scroll bars) and PR #267 (PDFJS_URL param fix). Hat tip to Theo Beers, Sascha Greuel, meier-andersen, and everyone who helped identify and confirm the underlying issues.
    • Fixed fallbackLink handling to ensure false is respected. Hat tip to Theo Beers.
  • 2.2.7, September 2021: Add title attribute to PDFJS iframe, per issue #258.
  • 2.2.6, July 2021:
    • Add title attribute to embed and iframe elements per issue #248.
    • Force Safari desktop to embed via iframe due to freezing bug in macOS 11 (Big Sur) per issue #243.
    • Fixed version number per issue #247.
    • Added note about documentation to readme file per issue #251.
  • 2.2.5, March 2021:
    • Expanded assumptions to counteract Chrome's deprecation of MIME type checks. Any 'modern' browser will be given a green light regardless of whether assumptionMode is enabled. However assumptionMode will still be available for browsers that are not declared modern.
    • Added allow="fullscreen" attribute to iframe embeds, in case anyone needs their PDFs to be rendered fullscreen
    • Fixed Firefox user agent sniffing for edge case (thanks to David Novodchuck for the PR).
  • 2.2.4, October 2020: Reinstated typeof check for window to play nice with React and NextJS.
  • 2.2.3, September 2020: Version bump for NPM. Sigh.
  • 2.2.2, September 2020: Fixed typo affecting `suppressConsole` functionality. Hat tip to John Hunter for the discovery and fix.
  • 2.2.1, September 2020: Fixed typo affecting styling of iframe when forcing PDFJS.
  • 2.2.0, September 2020:
    • New behavior: Dropping support for IE9 and IE10, which have practically 0 marketshare now.
    • New behavior: Now explicitly displaying fallback content for all mobile devices, even "Request Desktop" version of pages in iOS. The reasoning is simple: As the time of this update, no mobile device (Android, iOS) natively supports embedded PDFs. This change will lead to a consistent experience across all mobile devices. PDFs can be rendered via PDF.js on mobile if embedding on mobile is a critical need. PDF.js is not included with PDFObject.
    • New option: Omit inline styles by setting option omitInlineStyles to true. This helps developers who use strict environments where inline styles are not allowed. Note you will be responsible for applying proper styling via your own CSS.
    • New option: Suppress console logging by setting option suppressConsole to true. PDFObject currently places error messages in the console if the PDF can't be embedded for some reason. This option allows you to mute those alerts.
    • New option: Force PDFObject to embed the PDF in an iframe (instead of an <embed>) by setting forceIframe to true.
    • New option: On macOS systems, Safari does not properly embed PDFs that have been requested via 302 URL redirection when embedding using the <embed> element. Setting supportRedirect to true forces PDFObject to use an <iframe> instead of an <embed> for desktop Safari. Hat tip to John Hunter for the discovery and fix.
    • Refactored to use more modern code conventions, such as let in lieu of var, el.classList.add() in place of el.className = 'foo', and myvar === undefined in place of typeof myvar === "undefined". Implemented a let declaration before each variable instead of the Crockford practice of one var per function.
    • Refactored to make code safer for server-side node.js-based environments.
    • Refactored to eliminate string-based element creation via innerHTML. Replaced with standard DOM methods. This helps alleviate unforeseen issues with file names. Only exception is insertion of fallback content, which is passed as a string via innerHTML.
    • Removed iframe scrollfix for iOS, as it is no longer needed as of iOS13. iOS 12 and lower have ~5-7% marketshare and shrinking fast.
    • Refactored codebase to make it more concise and legible.
  • 2.1.1, October 2018: Changed handling of iOS to reflect Safari's lack of support for embedding inline PDFs. (In iOS, Safari will only display an image preview of the first page of a PDF, and will not render other pages of the PDF.) Other iOS web browsers use Apple's native WebView to render pages, which leads to the same limitations as Safari. Therefore, PDFObject now assumes any iOS-based web browsers will not support PDF embedding.
  • 2.1, October 2018: Changed assumptionMode default from false to true. This will ensure PDFObject 2.x will work for Firefox users without requiring them to change their codebase to enable assumptionMode. All they need to do is load the latest version of PDFObject, the PDFObject utility will take care of the rest.
  • 2.1 (dev branch), January 2017: Modified to support Mozilla's removal of navigator.mimeTypes inspection. Added assumptionMode for manual override of PDFObject's default navigator.mimeTypes sniffing.
  • 2.0, April 2016: Initial release of PDFObject 2.0. Contains breaking changes, and is not compatible with PDFObject 1.x.