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.
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.
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");
}
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 totrue
, 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.assumptionMode
is a direct response to Mozilla's decision to removenavigator.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 querynavigator.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
andiframe
elements. For example, you could specify theloading
attribute on the iframe to be"lazy"
.Values must be set as
key
andvalue
, as shown in the following example:var options = { customAttribute: { key: "foo", value: "bar" } }; PDFObject.embed("myfile.pdf", "#my-container", options);
-
fallbackLink [string] or [boolean]. Default:
"<p>This browser does not support inline PDFs. Please download the PDF to view it: <a href='[url]'>Download PDF</a></p>"
Any string entered here will be inserted into the target element when the browser doesn't support inline PDFs.
- HTML is supported
- Use the shortcode
[url]
to insert the URL of the PDF (as specified via the URL parameter in theembed()
method).var options = { fallbackLink: "<p>This is a <a href='[url]'>fallback link</a></p>" }; PDFObject.embed("myfile.pdf", "#my-container", options); //If browser doesn't support inline PDFs, outputs: //<p>This is a <a href='myfile.pdf'>fallback link</a></p>
- Entering
false
will disable the fallback text option and prevent PDFObject from inserting fallback textPDFObject.embed("myfile.pdf", "#my-container", {fallbackLink: false}); //If browser doesn't support inline PDFs, outputs nothing
-
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 thePDFJS_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 totrue
.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 supportspage
,zoom
,nameddest
, andpagemode
.page
is the most widely-supported PDF Open Parameter outside of Adobe products.
Note that PDFObject provides a convenient alias forPDFObject.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
page
so you don't need to use thepdfOpenParams
child object. All other PDF Open Parameters need to be listed as children of thepdfOpenParams
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. SettingsupportRedirect
totrue
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 totrue
.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;">
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);
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>
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
Examples
The following links demonstrate the many ways PDFObject can be utilized.
- Invoking conditional JavaScript upon successful embed (onclick)
- Invoking conditional JavaScript upon successful embed
- Detection of PDF support
- Detection using navigator.pdfViewerEnabled
- Embed two PDFs on one HTML page
- Full-browser embed (no selector specified)
- Full-browser embed (explicit selector) with PDF Open Params specified
- Full-browser embed (explicit selector)
- Full-browser embed, forced iframe
- Passing jQuery element, CSS styles applied
- Passing jQuery element
- Passing vanilla HTML element, CSS styles applied
- Passing vanilla HTML element
- Passing CSS selector, CSS styles applied
- Passing CSS selector
- PDF.js (forced)
- PDF.js fallback
- Specifying PDF URL containing querystring, with PDF Open Parameters
- Specifying PDF URL containing querystring
- Replace one PDF with another
- Specifying custom fallback link
- Declining to provide a fallback link
- Embedding a PDF encoded as a base64 string
- Specifying PDF URL that will redirect via 302 to a different URL
- Forcing PDFObject to use an iframe for embeds
- Embed the PDF without any inline styles (relies on external CSS for proper display)
- Embed the PDF without any inline styles, and also require PDF to use an iframe to embed the PDF
- Embedding a file with spaces and an apostrophe in the filename
- Setting the title attribute on the embed element
- Specifying custom attribute
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
andiframe
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 ensurefalse
is respected. Hat tip to Theo Beers.
- Refactored to reduce redundant code. Simplified iframe and PDFJS handling. Subsequently resolves #263 (double scroll bars) and PR #267 (
- 2.2.7, September 2021: Add title attribute to PDFJS iframe, per issue #258.
- 2.2.6, July 2021:
- Add title attribute to
embed
andiframe
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.
- Add title attribute to
- 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 forwindow
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
totrue
. 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
totrue
. 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 settingforceIframe
totrue
. - 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. SettingsupportRedirect
totrue
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 ofvar
,el.classList.add()
in place ofel.className = 'foo'
, andmyvar === undefined
in place oftypeof myvar === "undefined"
. Implemented alet
declaration before each variable instead of the Crockford practice of onevar
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 viainnerHTML
. - 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 fromfalse
totrue
. This will ensure PDFObject 2.x will work for Firefox users without requiring them to change their codebase to enableassumptionMode
. 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. AddedassumptionMode
for manual override of PDFObject's defaultnavigator.mimeTypes
sniffing. - 2.0, April 2016: Initial release of PDFObject 2.0. Contains breaking changes, and is not compatible with PDFObject 1.x.
1. Create a container to hold your PDF
2. Tell PDFObject which PDF to embed, and where to embed it
3. You can optionally use CSS to change the appearance of the containing element, such as height, width, border, margins, etc.