Nada Rifki Nada is a JavaScript developer who likes to play with UI components to create interfaces with great UX. She specializes in Vue.js and loves sharing anything and everything that could help her fellow frontend web developers. Nada also dabbles in digital marketing, dance, and Chinese.
Table of contentsLogRocket’s Galileo AI watches every session, surfacing impactful user struggle and key behavior patterns.
Editor’s note: This article was last updated by Joseph Mawa on 6 June 2024 to introduce alternatives to iframes, such as using the Fetch API to load dynamic content, in the case where you don’t want to risk the instability of iframes. It now also includes additional methods for ensuring iframe security, such as using the referrerpolicy attribute in addition to the sandbox and allow attributes.
Introduced by Microsoft Internet Explorer in 1997 with HTML 4.01, the iframe element (short for inline frame) is among the oldest HTML tags. And though all modern browsers support them, many developers write endless articles advising against using iframes. Their bad reputation should not prevent you from relying on them, however, as they have many significant use cases. It is also not difficult to secure them, so you won’t have to worry about your user’s machine becoming compromised by using iframes.
To help you form your own opinion and sharpen your developer skills, this article will cover all the essentials you should know about this controversial HTML element. We’ll go through most of the features the iframe element provides and talk about how you use them, as well as how iframes can be useful for overcoming some tricky situations. Finally, we’ll talk about how you can secure your iframes to avoid potential vulnerabilities.
Developers mainly use the iframe tag to embed an HTML document within another. You may have crossed paths with it when you had to include a third-party widget (like the famous Facebook “like” button), a YouTube video, or an advertising section on your website.
For example, the code below will display a 500px square with a YouTube video inside:
Here is another example in which we display a button to post on X:
What you must remember when thinking about iframes is that they let you embed an independent HTML document with its own browsing context. Thus, it will be isolated from the parent’s JavaScript and CSS.
That is one of the valid purposes for using an iframe: to provide a measure of separation between your application and the iframe content. Nevertheless, as you will see in this guide, the separation is not perfect.
The iframe can still behave in annoying or malicious ways — triggering a popup or auto-playing videos, for example. To illustrate how this isolation from the JavaScript and CSS is handy, let’s take a look at two example scenarios.
In an application, a user could create emails and save them as templates. On a particular page, I needed to list them to let the user preview and choose one. And to prevent the CSS of the current website from affecting the style of these templates, I figured out that using an iframe with the srcdoc attribute was the cleanest solution:
The other situation when iframes helped me was when I built a WYSIWYG editor for a customer. But the thing with these editors is that you must find a way to maintain the focus and selection when the user is clicking on all the buttons across the interface.
Because an iframe offers an isolated environment, the focus or selection is never lost when you are clicking outside of it. By using communication events between the iframe and the parent (more on how to do so later in this article), I managed to easily design a powerful editor.
There are several attributes we can use to customize the behavior or styling of an iframe:
html
You may find more than the ones listed above, but keep in mind that some are not supported in HTML5 anymore: align , frameborder , longdesc , marginheight , marginwidth , and scrolling .
Note that, by default, the iframe element has a border around it. To remove it, you can use the style attribute to set the CSS border property to none :
When you are loading the iframe, the load event comes in handy for improving user experience, like displaying a spinner or a specific message to indicate to the user that the iframe is still loading:
You can listen to the load event with the onload attribute:
Or you can add the event listeners to your iframe programmatically in JavaScript:
// For a new iframe const iframe = document.createElement("iframe"); iframe.onload = function(e) < console.log("The iframe is loaded"); >; // or using the addEventListener method iframe.addEventListener("load", (e) => < console.log("The iframe is loaded"); >); iframe.src = "https://logrocket.com/"; document.body.appendChild(iframe); // For an existing iframe const iframe = document.querySelector('.my-iframe'); iframe.onload = function() < console.log("The iframe is loaded"); >// or using the addEventListener method iframe.addEventListener("load", (e) => < console.log("The iframe is loaded"); >);
It is quite easy to send messages between the parent and the iframe; you have to use the postMessage function.
In the following example, we demonstrate how to send a message from the parent to the iframe. This code snippet demonstrates how to send the message from the parent element:
const myiframe = document.getElementById('myIframe') myIframe.contentWindow.postMessage('message', '*');
And the following code illustrates how to listen to the message in the iframe:
window.onmessage = function (event) < if (event.data == "message") < console("Message received!"); >>;
As for sending a message from the iframe to the parent, the following code demonstrates how to send the message from the iframe:
window.top.postMessage('reply', '*')
This code snippet shows how to listen to it in the parent:
window.onmessage = function (event) < if (event.data == "reply") < console("Reply received!"); >>;
N.B., keep in mind that you can end up in some tricky situations when you need to debug something, as messages are fire-and-forget (i.e., there is no real error handling).
When you are using an iframe, you are most likely dealing with content from a third party over which you have no control. Thus, you are increasing the risk of introducing a vulnerability to your application or simply dealing with a bad user experience (like annoying video autoplay).
Thankfully, you can block or allow specific features by using the sandbox and allow attributes we discussed earlier.
A good rule of thumb is to always grant the minimum level of capability necessary to a resource to do its job. Security experts refer to this concept as “the principle of least privilege.”
You can set the value of the sandbox attribute to an empty string to restrict JavaScript and all the features in the table below. On the other hand, you can lift certain restrictions by setting the value of the sandbox attribute to a space-delimited list of flags. Here is the complete list of iframe sandboxing flags and their purposes:
Flag | Details |
---|---|
allow-forms | Allows form submission |
allow-modals | Allows the resource to open new modal windows |
allow-orientation-lock | Allows the resource to lock the screen orientation |
allow-pointer-lock | Allows the resource to use the Pointer Lock API |
allow-popups | Allows the resource to open new popups or tabs |
allow-popups-to-escape-sandbox | Allows the resource to open new windows that will not inherit the sandboxing |
allow-presentation | Allows the resource to start a presentation session |
allow-same-origin | Allows the resource to maintain its origin |
allow-scripts | Allows the resource to run scripts |
allow-top-navigation | Allows the resource to navigate the top-level browsing context |
allow-top-navigation-by-user-activation | Allows the resource to navigate the top-level browsing context, but only if initiated by a user gesture |
It is up to you to define which privileges you grant to each iframe. For example, if your iframe only needs to submit forms and open new modal windows, here is how you would configure the sandbox attribute:
It is recommended that you grant embedded content, including iframes, only the minimum privileges for them to do their job.
Learn more →
For a situation when the sandbox attribute is configured, and one feature is not working correctly within the resource, it might be because it lacks a specific flag. Make sure you know more about them to debug things quickly.
As highlighted above, using an empty sandbox attribute will fully sandbox the iframe. This means that the JavaScript inside the iframe will not be executed, and all the privileges listed above will be restricted (like creating new windows or loading a plugin).
The empty sandbox attribute is mostly used for static content but will drastically reduce the capability required for the other iframe resources to work properly.
N.B., the sandbox attribute is unsupported in Internet Explorer 9 and earlier.
The allow attribute lets you enable and disable specific features in an iframe. These features include autoplay, access to the accelerometer interface, battery information, and the camera. Be sure to check Can I Use for details on cross-browser support.
Some of these features may be sensitive and intrusive, especially when you’re embedding content from a third party. They have implications for the security and privacy of your users. Therefore, you should only use iframes from trusted sources and grant them such sensitive permissions if you’re certain the content you embed in the iframe won’t violate the privacy of your users.
There are more than 25 available flags. I have summarized the most popular in the table below:
Flag | Details |
---|---|
accelerometer | Allows access to the Accelerometer interface |
ambient-light-sensor | Allows access to the AmbientLightSensor interface |
autoplay | Allows the autoplay of video and audio files |
battery | Allows access to the Battery Status API |
camera | Allows access to the camera |
fullscreen | Allows access to fullscreen mode |
geolocation | Allows access to the Geolocation API |
gyroscope | Allows access to the Sensors API Gyroscope interface |
magnetometer | Allows access to the Sensors API Magnetometer interface |
microphone | Allows access to the device microphone |
midi | Allows access to the Web MIDI API |
payment | Allows access to the Payment Request API |
usb | Allows access to the WebUSB API |
vibrate | Allows access to the Vibration API |
referrerpolicy is another attribute for handling security in iframes. Usually, when the browser requests a resource such as an image or iframe, it sends the full or partial address of the page requesting the resource in the Referer request header:
Referer:The server can use the partial or full URL sent in the Referer header to identify the page requesting the resource for analytics and resource optimization.
On the other hand, the Referer header makes it easy to accidentally leak sensitive data such as passwords and usernames. If you load a third-party iframe in a page that contains sensitive data in the URL without proper referrer policy settings, you may accidentally expose private data.
You can use the referrer policy to control the data sent in the Referer header. You can configure the referrer policy by setting the HTTP Referrer-Policy response header to one of the values below:
Referrer-Policy: no-referrer Referrer-Policy: no-referrer-when-downgrade Referrer-Policy: origin Referrer-Policy: origin-when-cross-origin Referrer-Policy: same-origin Referrer-Policy: strict-origin Referrer-Policy: strict-origin-when-cross-origin Referrer-Policy: unsafe-url
The strictest value is no-referrer . When you set the referrer policy to no-referrer , the Referrer header will be omitted. You can look up the interpretation of the other directives in the documentation.
If you don’t explicitly specify the referrer policy or when you set an invalid value, the browser defaults to strict-origin-when-cross-origin .
You can also specify the referrer policy in HTML using the tag. It sets the referrer policy for the entire document:
You can also set the referrer policy for individual iframes like so:
If you don’t securely configure your referrer policy, you may accidentally leak sensitive information. Among other measures, it’s recommended you avoid using iframes from third parties on pages that contain login and payment forms. You can also set the referrer policy to no-referrer or other more secure options.
If a browser does not support an iframe, it will display the content between the opening tag.
Thus, you should always think about placing a warning message as a fallback for such users:
As we mentioned earlier, browsers render iframes with a border by default. You can remove the border using CSS by setting the border property to none :
There’s a lot of speculation around this subject.
For a long time, crawlers could not understand iframes, but this is no longer the case. The most relevant answer I found was from this article, and today’s conclusion seems to be:
Since search engines consider the content in iframes to belong to another website, the best you can hope for is no effect. iframes tend to neither help nor hurt your search engine ranking.
Thus, it is best to assume that the content displayed via iframes may not be indexed or available to appear in Google’s search results. A workaround would be to provide additional text-based links to the content they display so that Google crawlers can find and index this content.
N.B., you should also not worry about duplicate content issues because today’s web crawlers usually recognize that.
Every iframe on a page will increase the memory used, as well as other computing resources like your bandwidth. So you should not use iframes excessively without monitoring what’s going on, or you might end up harming your page performance.
To avoid having your iframes slow down your pages, a good technique is to lazy load them (i.e., loading them only when they are required, like when the user scrolls near them). This can be achieved easily just by adding the loading="lazy" attribute to the tag.
All modern desktop browsers support lazy loading. However, support is lacking in some mobile browsers. For something that works everywhere, you may be interested in the LazyLoad library:
N.B., the loading="lazy" attribute also works with the img tag, in case you didn’t know that already. 😜
Easy peasy lemon squeezy! As you can access the window element of the iframe with contentWindow , you have to do this:
// Get the iframe const iframe = document.getElementById('myIframe'); // Reload the iframe iframe.contentWindow.location.reload();
As explained above, you can work with iframes in JavaScript like any other HTML element. You can use the contentWindow property to access the window object of the embedded iframe from the parent if both are from the same origin:
const iframe = document.getElementById("my-iframe"); iframe.addEventListener("load", (e) => < iframe.contentWindow.document.body.style.backgroundColor = "yellow"; >);
After accessing the iframe’s document object, you can use JavaScript to manipulate its contents from the parent as in the example above. Similarly, an iframe can access its parent using the window.parent property.
However, you need to be aware that this is only possible if the iframe has the same origin as its parent. For different origins, accessing the contentWindow.document will throw an error. If the iframe and its parent are from different origins, you need to use the postMessage method explained in one of the previous sections.
Instead of accessing the embedded iframe document using the iframe.contentWindow property like in the above example, you can also use the iframe.contentDocument property directly like so:
const iframe = document.getElementById("my-iframe"); iframe.addEventListener("load", (e) => < iframe.contentDocument.body.style.backgroundColor = "yellow"; >);
You need to wait for the iframe to fully load before accessing and manipulating its DOM. Therefore, you need to wait for the load event to fire. The load event is emitted after fully loading the iframe and its resources.
As mentioned above, iframes come in handy for embedding content like videos. However, these iframes come with potential security vulnerabilities and overheads such as bandwidth and memory usage. Because of these drawbacks, it would be helpful to know some iframe alternatives.
These alternatives may not have all the features of iframes but they can be useful replacements in certain use cases so that you don’t need to deal with the risks and overhead of using iframes.
Use the Fetch API when dealing with dynamic content instead of loading iframes. You fetch data from an external source using the Fetch API instead of loading them in iframes.
This gives you the freedom to render and style the content flexibly because, unlike iframes, the content you load via the Fetch API is headless. You can then render the content using the relevant HTML elements, therefore removing the need for iframes and their associated drawbacks.
With HTML5 web components, you can create custom reusable components that you can import into your project, therefore removing the need to use iframes for loading simple same-origin HTML markup. It also gives you total control over the styling and behavior of the component.
As explained above, it is not uncommon for sites to embed third-party widgets such as the “Post” button from X using iframes. Because each iframe you load comes with its own resource, it increases your site’s bandwidth and memory usage.
You can easily recreate some of these widgets using basic HTML elements and JavaScript, removing the need to load third-party iframes.
Most of the time, a screen reader will indicate that an iframe is present on the page. Many will even enable you to navigate inside. If your iframe does not contain another webpage but instead contains external content like a video player or an ad, it is essential to add a title to the tag to give users more context for what the iframe is about:
Some will say that this attribute is not essential because most screen readers will only read the document’s title when available and skip the title attribute on the iframe tag. However, for the same title to be read correctly across various screen readers, it is good practice to provide both and to make sure they match.
Another thing to keep in mind is that when your iframe includes non-readable content (like, for example, a video game built with JavaScript), you will have to hide its contents from screen reader users using the aria-hidden attribute:
We talked about this at the beginning of this guide, but make sure to include some content inside the iframe for all the older browsers that do not support them. This will give more context to everyone about what should be displayed in the space:
I hope this guide has helped you to improve your knowledge of iframes.
While they can be insecure if you’re loading untrusted content, they also offer some significant advantages. So you should not ban them entirely from your developing arsenal but only use them in relevant situations.
If you have anything to add to this article, you can reach me in the comments below or just ping me on X @RifkiNada.
Would you be interested in joining LogRocket's developer community?
Yea No ThanksJoin LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Formik is a small JavaScript library built in response to the hardships experienced when creating large forms in React.
Sep 4, 2024 ⋅ 14 min readThe hamburger menu icon is a common design element in mobile and responsive websites and applications. It offers a compact […]
Sep 4, 2024 ⋅ 8 min readExplore the new Promise.withResolvers() mechanism to create a JavaScript Promise and cancel it before its completion.
Sep 3, 2024 ⋅ 5 min readExplore Telegram Mini Apps and the benefits they provide as we build and deploy a fullstack, ecommerce React app on Telegram.