The iframeResizer library enables automatic resizing for iFrames of the height, the width or both to fit their contained content on same and cross domain.
The library provides a wide range of features to address the most common issues using iFrames on webpages which includes:
-
Height and width resizing of the iFrame to content size
-
Works with multiple and nested iFrames
-
Domain authentication for cross domain iFrames
-
Provides a range of page size calculation methods to support complex CSS layouts
-
Detects changes to the DOM that can cause the page to resize using MutationObserver
-
Detects events that can cause the page to resize (Window Resize, CSS Animation and Transition, Orientation Change and Mouse events)
-
Simplified messaging between iFrame and host page via postMessage
-
Fixes in page links in iFrame and supports links between the iFrame and parent page
-
Provides custom sizing and scrolling methods
-
Exposes parent position and viewport size to the iFrame
-
Provides onMouseEnter and onMouseLeave events for the iFrame
-
Works with ViewerJS to support PDF and ODF documents
J1 Integration
Temporibus deleniti molestiae sint qui quaerat voluptas et non ducimus quia minus aspernatur deleniti. Sint minus optio explicabo. Velit omnis harum voluptatem. Nesciunt sapiente eveniet libero consequuntur pariatur ratione vitae nam. Quibusdam alias eligendi cupiditate laudantium.
Eius quia omnis incidunt ut velit quae excepturi et aut quia dolorem quasi consequuntur corporis. Aut dolor ea quos. In quis unde aspernatur dolores vel officiis exercitationem ut quia odit quisquam amet autem.
Manual Setup
The package contains two (minified) JavaScript files in the folder ~/assets/themes/j1/modules/iframeResizer/js
. The JS file iframeResizer.js
is for the page hosting the iFrames.
It can be called with via JavaScript:
const iframes = iFrameResize( [{options}], [css selector] || [iframe] );
The second JS file client/iframeResizer.contentWindow.js
needs placing in the page(s) contained within your iFrame. This file is designed to be a guest on someone else’s system, so has no dependencies and won’t do anything until it’s activated by a message from the containing page.
Typical setup
The normal configuration is to have the iFrame resize when the browser window changes size or the content of the iFrame changes. To set this up you need to configure one of the dimensions of the iFrame to a percentage and tell the library to only update the other dimension. Normally you would set the width to 100% and have the height scale to fit the content.
<style>
iframe {
width: 1px;
min-width: 100%;
}
</style>
<script src="/assets/themes/j1/modules/iframeResizer/js/iframeResizer.min.js"></script>
<iframe id="myIframe" src="http://anotherdomain.com/iframe.html"></iframe>
<script>
iFrameResize({
log: true
},
'#myIframe'
)
</script>
Using min-width to set the width of the iFrame, works around an issue in iOS that can prevent the iFrame from sizing correctly. |
In case of problems, check the Troubleshooting section.
Parent Page API
IFrame-Resizer provides an extensive range of options and APIs for both the parent page and the iframed page.
Options
The following options can be passed to iframe-resizer on the parent page.
log
Setting the log
option to true will make the scripts in both the host page and the iFrame output everything they do to the JavaScript console so you can see the communication between the two scripts.
default: false type: boolean
autoResize
When enabled changes to the Window size or the DOM will cause the iFrame to resize to the new content size. Disable if using size method with custom dimensions.
When set to false the iFrame will still inititally size to the contained content, only additional resizing events are disabled. |
default: true type: boolean
bodyBackground
Override the body background style in the iFrame.
default: null type: string
bodyMargin
Override the default body margin style in the iFrame. A string can be any valid value for the CSS margin attribute, for example `8px 3em'. A number value is converted into px.
default: null type: string || number
bodyPadding
Override the default body padding style in the iFrame. A string can be any valid value for the CSS margin attribute, for example `8px 3em'. A number value is converted into px.
default: null type: string || number
checkOrigin
When set to true, only allow incoming messages from the domain listed in the src
property of the iFrame tag. If your iFrame navigates between different domains, ports or protocols; then you will need to provide an array of URLs or disable this option.
default: true type: boolean || array
inPageLinks
When enabled in page linking inside the iFrame and from the iFrame to the parent page will be enabled.
default: false type: boolean
heightCalculationMethod
By default the height of the iFrame is calculated by converting the margin of the body
to px and then adding the top and bottom figures to the offsetHeight of the body
tag.
In cases where CSS styles causes the content to flow outside the body
you may need to change this setting to one of the following options. Each can give different values depending on how CSS is used in the page and each has varying side-effects. You will need to experiment to see which is best for any particular circumstance.
-
bodyOffset uses
document.body.offsetHeight
-
bodyScroll uses
document.body.scrollHeight
* -
documentElementOffset uses
document.documentElement.offsetHeight
-
documentElementScroll uses
document.documentElement.scrollHeight
* -
max takes the largest value of the main four options *
-
min takes the smallest value of the main four options *
-
lowestElement Loops though every element in the DOM and finds the lowest bottom point †
-
taggedElement Finds the bottom of the lowest element with a
data-iframe-height
attribute
default: 'bodyOffset' values: 'bodyOffset' | 'bodyScroll' | 'documentElementOffset' | 'documentElementScroll' | 'max' | 'min' | 'grow' | 'lowestElement' | 'taggedElement'
If the default option doesn’t work then the best solutions is to use either** taggedElement, or lowestElement*.* Alternatively it is possible to add your own custom sizing method directly inside the iFrame, see the iFrame Page Options section for more details. The lowestElement option is the most reliable way of determining the page height. However, it does have a performance impact, as it requires checking the position of every element on the page. The taggedElement option provides much greater performance by limiting the number of elements that need their position checked. These methods may cause screen flicker in some browsers. |
maxHeight / maxWidth
Set maximum height/width of iFrame.
default: infinity type: integer
minHeight / minWidth
Set minimum height/width of iFrame.
default: 0 type: integer
resizeFrom
Listen for resize events from the parent page, or the iFrame. Select the `child' value if the iFrame can be resized independently of the browser window. Selecting this value can cause issues with some height calculation methods on mobile devices.
default: 'parent' values: 'parent', 'child'
scrolling
Enable or disable scroll bars for the iFrame.
-
true applies to
scrolling="yes"
-
false applies to
scrolling="no"
default: false type: boolean
sizeHeight
Resize iFrame to content height.
default: true type: boolean
sizeWidth
Resize iFrame to content width.
default: false type: boolean
tolerance
Set the number of pixels the iFrame content size has to change by, before triggering a resize of the iFrame.
default: 0 type: integer
warningTimeout
Set the number of milliseconds after which a warning is logged if the iFrame has not responded. Set to 0
to supress warning messages of this type.
default: 5000 type: integer
widthCalculationMethod
By default the width of the page is worked out by taking the greater of the documentElement and body scrollWidth values.
Some CSS techniques may require you to change this setting to one of the following options. Each can give different values depending on how CSS is used in the page and each has varying side-effects. You will need to experiment to see which is best for any particular circumstance.
-
bodyOffset uses
document.body.offsetWidth
-
bodyScroll uses
document.body.scrollWidth
* -
documentElementOffset uses
document.documentElement.offsetWidth
-
documentElementScroll uses
document.documentElement.scrollWidth
* -
scroll takes the largest value of the two scroll options *
-
max takes the largest value of the main four options *
-
min takes the smallest value of the main four options *
-
rightMostElement Loops though every element in the DOM and finds the right most point †
-
taggedElement Finds the left most element with a
data-iframe-width
attribute
Alternatively it is possible to add your own custom sizing method directly inside the iFrame, see the iFrame Page Options section for more details
The rightMostElement option is the most reliable way of determining the page width. However, it does have a performance impact as it requires calculating the position of every element on the page. The taggedElement option provides much greater performance by limiting the number of elements that need their position checked. These methods can cause screen flicker in some browsers. |
default: 'scroll' values: 'bodyOffset' | 'bodyScroll' | 'documentElementOffset' | 'documentElementScroll' | 'max' | 'min' | 'scroll' | 'rightMostElement' | 'taggedElement'
Methods
Once the iFrame has been initialized, an iFrameResizer
object is bound to it. This has the following methods available.
close()
Remove the iFrame from the page.
moveToAnchor(anchor)
Move to anchor in iFrame.
removeListeners()
Detach event listeners from iFrame. This is option allows Virtual DOMs to remove an iFrame tag. It should not normally be required.
resize()
Tell the iFrame to resize itself.
sendMessage(message, [targetOrigin])
Send data to the containing page, message
can be any data type that can be serialized into JSON. The targetOrigin
option is used to restrict where the message is sent to, in case your iFrame navigates away to another domain.
Events
The following callback events can be passed to iframe-resizer on the parent page, as part of the options object.
onClose
Called before iFrame is closed via parentIFrame.close()
or iframe.iFrameResizer.close()
methods. Returning false
will prevent the iFrame from closing.
onClose: (iframeID) => boolean
onClosed
Called after iFrame is closed via parentIFrame.close()
or iframe.iFrameResizer.close()
methods.
onClosed: (iframeID) => undefined
onInit
Called after initial setup.
onInit: (iframe) => undefined
onMessage
Receive message posted from iFrame with the parentIFrame.sendMessage()
method.
onMessage: ({iframe,message}) => undefined
onMouseEnter
Function called after the mouse enters the iframe. Passes messageData
object containing the iFrame, screenX, screenY and the type of event that triggered the callback.
onMouseEnter: ({iframe,height,width,type}) => undefined
onMouseLeave
Function called after the mouse leaves the iframe. Passes messageData
object containing the iFrame, screenX, screenY and the type of event that triggered the callback.
onMouseLeave: ({iframe,height,width,type}) => undefined
onResized
Function called after iFrame resized. Passes messageData
object containing the iFrame, height, width and the type of event that triggered the iFrame to resize.
onResized: ({iframe,height,width,type}) => undefined
onScroll
Called before the page is repositioned after a request from the iFrame, due to either an in page link, or a direct request from either parentIFrame.scrollTo() or parentIFrame.scrollToOffset(). If this function returns false, it will stop the library from repositioning the page, so that you can implement your own animated page scrolling instead.
onScroll: ({x,y}) => [true|false]
IFramed Page API
Options
The following options can be set from within the iFrame page by creating a window.iFrameResizer
object before the JavaScript file is loaded into the page.
<script>
window.iFrameResizer = {
targetOrigin: 'http://mydomain.com'
}
</script>
<script src="js/iframeresizer.contentwindow.js"></script>
targetOrigin
This option allows you to restrict the domain of the parent page, to prevent other sites mimicking your parent page.
default: '*' type: string
heightCalculationMethod / widthCalculationMethod
These options can be used to override the option set in the parent page (See above for details on available values). This can be useful when moving between pages in the iFrame that require different values for these options.
Altenatively you can pass a custom function that returns the size as an integer. This can be useful when none of the standard ways of working out the size are suitable. However, normally problems with sizing are due to CSS issues and this should be looked at first.
default: null type: string | function() { return integer }
Methods
These methods are available in the iFrame via the window.parentIFrame
object. These method should be contained by a test for the window.parentIFrame
object, in case the page is not loaded inside an iFrame. For example:
if ('parentIFrame' in window) {
parentIFrame.close()
}
autoResize([bool])
Turn autoResizing of the iFrame on and off. Returns bool of current state.
close()
Remove the iFrame from the parent page.
getId()
Returns the ID of the iFrame that the page is contained in.
getPageInfo(callback || false)
Ask the containing page for its positioning coordinates. You need to provide a callback which receives an object with the following properties:
-
iframeHeight The height of the iframe in pixels
-
iframeWidth The width of the iframe in pixels
-
offsetLeft The number of pixels between the left edge of the containing page and the left edge of the iframe
-
offsetTop The number of pixels between the top edge of the containing page and the top edge of the iframe
-
scrollLeft The number of pixels between the left edge of the iframe and the left edge of the iframe viewport
-
scrollTop The number of pixels between the top edge of the iframe and the top edge of the iframe viewport
-
documentHeight The containing document’s height in pixels (the equivalent of
document.documentElement.clientHeight
in the container) -
documentWidth The containing document’s width in pixels (the equivalent of
document.documentElement.clientWidth
in the container) -
windowHeight The containing window’s height in pixels (the equivalent of
window.innerHeight
in the container) -
windowWidth The containing window’s width in pixels (the equivalent of
window.innerWidth
in the container) -
clientHeight (deprecated) The height of the containing document, considering the viewport, in pixels (
max(documentHeight, windowHeight)
). -
clientWidth (deprecated) The width of the containing document, considering the viewport, in pixels (
max(documentWidth, windowWidth)
).
Your callback function will be recalled when the parent page is scrolled or resized.
Pass false
to disable the callback.
scrollTo(x,y)
Scroll the parent page to the coordinates x and y.
scrollToOffset(x,y)
Scroll the parent page to the coordinates x and y relative to the position of the iFrame.
sendMessage(message,[targetOrigin])
Send data to the containing page, message
can be any data type that can be serialized into JSON. The targetOrigin
option is used to restrict where the message is sent to; to stop an attacker mimicking your parent page. See the MDN documentation on postMessage for more details.
setHeightCalculationMethod(heightCalculationMethod)
Change the method use to workout the height of the iFrame.
size ([customHeight],[ customWidth])
Manually force iFrame to resize. This method optionally accepts two arguments: customHeight & customWidth. To use them you need first to disable the autoResize
option to prevent auto resizing and enable the sizeWidth
option if you wish to set the width.
iFrameResize({
autoResize: false,
sizeWidth: true
})
Then you can call the size
method with dimensions:
if ('parentIFrame' in window) {
parentIFrame.size(100); // Set height to 100px
}
Events
The following events can be included in the options object attached to the iframed page.
onMessage
Receive message posted from the parent page with the iframe.iFrameResizer.sendMessage()
method.
type: function (message)
onReady
This function is called once iFrame-Resizer has been initialized after receiving a call from the parent page. If you need to call any of the parentIFrame methods during page load, then they should be called from this event handler.
type: function()
Use with jQuery
If jQuery is detected on the page, then this library provides a simple jQuery interface.
$('iframe').iFrameResize([{ options }])
Troubleshooting
The first steps to investigate a problem is to make sure you are using the latest version and then enable the log option, which outputs everything that happens to the JavaScript Console. This will enable you to see what both the iFrame and host page are up to and also see any JavaScript error messages.
Solutions for the most common problems are outlined in this section. If you need further help, then please ask questions on StackOverflow with the iframe-resizer
tag.
Bug reports and pull requests are welcome on the issue tracker. Please read the contributing guidelines before opening a ticket, as this will ensure a faster resolution.
Multiple IFrames
When the resizer does not work using multiple IFrames on one page, make sure that each frame has an unique id or no ids at all.
IFrame not sizing correctly
If a larger element of content is removed from the normal document flow, through the use of absolute positioning, it can prevent the browser working out the correct size of the page. In such cases you can change the heightCalculationMethod[options] to uses one of the other sizing methods.
IFrame not downsizing
The most likely cause of this problem is having set the height of an element to be 100% of the page somewhere in your CSS. This is normally on the html
or body
elements, but it could be on any element in the page. This can sometimes be got around by using the taggedElement
height calculation method and added a data-iframe-height
attribute to the element that you want to define the bottom position of the page. You may find it useful to use position: relative
on this element to define a bottom margin or allow space for a floating footer.
Not having a valid HTML document type in the iFrame can also sometimes prevent downsizing. At it’s most simplest this can be the following.
<!DOCTYPE html>
IFrame not resizing
The most common cause of this is not placing the iframeResizer.contentWindow.min.js script inside the iFramed page. If the other page is on a domain outside your control and you can not add JavaScript to that page, then now is the time to give up all hope of ever getting the iFrame to size to the content. As it is impossible to work out the size of the contained page, without using JavaScript on both the parent and child pages.
IFrame not detecting CSS :hover events
If your page resizes via CSS :hover
events, these won’t be detected by default. It is however possible to create mouseover
and mouseout
event listeners on the elements that are resized via CSS and have these events call the parentIFrame.size() method. With jQuery this can be done as follows
function resize(){
if ('parentIFrame' in window) {
// Fix race condition in FireFox with setTimeout
setTimeout(parentIFrame.size.bind(parentIFrame),0);
}
}
$(*Element with hover style*).hover(resize);
IFrame not detecting textarea resizes
Both FireFox and the WebKit based browsers allow the user to resize textarea
input boxes. Unfortunately the WebKit browsers don’t trigger the mutation event when this happens. This can be worked around to some extent with the following code.
function store() {
this.x = this.offsetWidth
this.y = this.offsetHeight
}
$('textarea')
.each(store)
.on('mouseover mouseout', function() {
if (this.offsetWidth !== this.x || this.offsetHeight !== this.y) {
store.call(this)
if ('parentIFrame' in window) {
parentIFrame.size()
}
}
})
IFrame flickers
Some of the alternate height calculation methods], such as max can cause the iFrame to flicker. This is due to the fact that to check for downsizing, the iFrame first has to be downsized before the new height can be worked out. This effect can be reduced by setting a minSize value, so that the iFrame is not reset to zero height before regrowing.
In modern browsers, if the default heightcalculation does not work, then it is normally best to use taggedElement or lowestElement, which are both flicker free.
Please see the notes section under heightcalculation to understand the limitations of the different options.
Localhost 127.0.0.1 and file:///
When an iframe is located on your local machine the browser adds extra security restrictions to cross-domain iframes. These will stop iframe-resizer from functioning. If you need to test something locally, then it is best to use the external IP Address of the machine.
Failed to execute `postMessage' on `DOMWindow'
This error occurs when the parent window tries to send a message to the iframe before it has loaded. IFrameResize makes multiple attempts to talk to the iFrame, so if everything is working then you can safely ignore this error message.
If you’re still having problems, or you really want to not ignore the error, then you can try delaying the call to iframeResize()
until after the onLoad
event of the iframe has fired.
If this does not fix the problem then check x-Frame-Options
http header on the server that is sending the iframe content, as this can also block calls to postMessage
if set incorrectly.
ParentIFrame not found errors
The parentIFrame
object is created once the iFrame has been initially resized. If you wish to use it during page load you will need call it from the onReady.
<script>
window.iFrameResizer = {
onReady: function() {
var myId = window.parentIFrame.getId()
console.log('The ID of the iFrame in the parent page is: ' + myId)
}
}
</script>
<script src="js/iframeresizer.contentwindow.js"></script>
PDF and OpenDocument files
It is not possible to add the required JavaScript to PDF and ODF files. However, you can get around this limitation by using ViewerJS to render these files inside a HTML page, that also contains the iFrame JavaScript file (iframeResizer.contentWindow.min.js).
Unexpected message received error
By default the origin of incoming messages is checked against the src
attribute of the iFrame. If they don’t match an error is thrown. This behaviour can be disabled by setting the checkOrigin option to false.
Width not resizing
By default only changes in height are detected, if you want to calculate the width you need to set the sizeWidth
option to true and the sizeHeight
option to false.
Frame has not responded within 5 seconds
This can happen when postMessage is being blocked in browser. There could be multiple reasons to that but in some cases we found that RocketLoader extension within Cloudflare was the reason. Try disabling it if you are using cloudflare.