Iframes are a commonly used resource on websites, with plenty of room for optimisation when it comes to web positioning (
An iframe is a floating frame that allows you to embed an HTML document within another. In the early webpages, it was commonly used to display different content from a separate page within frames.
However, nowadays the iframe is very useful when you need to embed externally hosted content. For example, when we want to insert content from other applications quickly without the need for APIs — such as YouTube videos or Google Maps content:
Iframes, like all multimedia content on a website, can be optimised for WPO (Web Performance Optimisation), usability, and Google’s understanding.
Thanks to the iframe tag, you can load content from other pages or documents, even from different domains (if they allow it). It enables much more varied and enriched content. Moreover, it has a wide range of attributes to experiment with depending on the objective.
However, this also has a major drawback. Although it provides a direct window to other content, it also loads all the resources from the page you are "embedding" through the iframe. This can severely affect the website’s loading speed.
Fortunately, there are several ways to use this feature without sacrificing user experience or speed.
This practice consists of not making the iframe call until the user clicks. The principle is similar to lazy loading, but instead of loading the iframe when the user views the element, the iframe is not loaded until the user clicks. But how well does it actually work?
If we create a page where only the iframe is active (without any elements that could alter the test), we find that it has already had to load all of the Google Maps content.
In total, this translates into:
51 server requests
290kB network transfer
1.4MB of total resources
Whereas if we use the On Load practice, we observe the following results until the user decides to interact — if they choose to do so:
As we can see, the results show a significant difference:
4 server requests compared to 51.
10.3KB network transfer compared to 290kB.
13.1KB of resources to download compared to 1.4MB.
More than double the loading speed.
Considering that iframes typically load heavy resources — as they are loading another website along with all its resources — this practice is generally an excellent strategy for Web Performance Optimisation (WPO).
There are many ways to achieve this effect; it is not the only method. For example, I will explain it using a CSS background; however, you could also use the srcdoc
attribute and remove it via JavaScript upon clicking, which would also be considered a good practice.
To understand how to do this, you need a basic working knowledge of HTML, CSS and JavaScript — skills taught to all students of the Technical SEO Master's programme at my company, Asdrubal. In any case, I have documented all the code on Codepen, and it can practically be copied and pasted directly — feel free to use all the code I am sharing here.
For the method I am using, a div
element containing the iframe is required, as simply placing an element above it with a z-index
will not work with iframes.
Both the div and the iframe will have a unique ID. The iframe will also have a defined width and height, as well as a specific class to hide the visibility of the element.<div id="iframeboxing">
<iframe id="iframeonclick" class="hidden" src="" width="600" height="450"></iframe>
</div>
And on the parent element, the div, we add an onclick attribute with the name of the function we are going to create (you could also do it with an addEventListener, using the same principle I use in the link obfuscation article).
We also add a background with the image we want the user to see so that they are encouraged to click on the iframe if they feel like using it. From a UX point of view, it’s important that it grabs attention and that its functionality is clear.
The background can be added inline as shown here, or you can add it via the CSS file without any problem.<div id="iframeboxing" onclick="load_on_iframe()" style="background: url('https://carlos.sanchezdonate.com/wp-content/uploads/onload-iframe.jpg');">
<iframe id="iframeonclick" class="hidden" src="" width="600" height="450">
</iframe>
</div>
In this case, we will target both of the created IDs and the hidden class we explained earlier. It’s important that the visibility is set to hidden.
For the parent element, Iframeboxing, we need to assign the same size that we have set for our div. It’s also important to add a cursor pointer so that users can easily guess that it’s a clickable element. We should also use position: relative and overflow: hidden to ensure it works properly.
As for the iframe, we’ll add a position: absolute so that it aligns with the parent element, along with the CSS hack to stick it to all four sides.#iframeboxing {
width: 600px;
padding-top: 450px;
cursor: pointer;
background-size: cover!important;
position: relative;
overflow: hidden;
}
#iframeonclick {
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
width: 100%; height: 100%;
border: none;
}
.hidden {
visibility: hidden;
}
Now it’s time to work some magic with JavaScript and make all of this functional:
We select the parent element and remove the onclick attribute so that the function is not executed every time the user clicks (although, in theory, they won’t be able to because the iframe will be placed on top).
We remove the class that hides the iframe from the iframe element.
We add the source (src) for the content we want to load into the iframe.
function load_on_iframe() {
document.getElementById("iframeboxing").setAttribute("onClick", "");
document.getElementById("iframeonclick").className = document.getElementById("iframeonclick").className.replace(/(?:^|\s)hidden(?!\S)/g, "");
document.getElementById("iframeonclick").src =
"https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d12640.309781091826!2d-0.9916284999999999!3d37.62386605!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1ses!2ses!4v1659971988650!5m2!1ses!2ses";
}
If we put all of that together, we get the effect shown in this CodePen (you can edit it and test different things as you like).
On the other hand, I’ll also leave the code for the lazy ones — just in case someone got lost and wants a quick and easy way to insert an iframe using this technique. Simply copy this code, paste it wherever you can add HTML, and change the green parts.<div id="iframeboxing" onclick="load_on_iframe()" style="background: url('PUT THE URL OF THE IMAGE BEFORE CLICKING HERE');">
<iframe id="iframeonclick" class="hidden" style="border: 0;" src="" width="600" height="450" allowfullscreen="allowfullscreen"></iframe></div>
<style>#iframeboxing{width:600px;padding-top:450px;margin:auto;cursor:pointer;background-size:cover!important;position:relative;overflow:hidden}#iframeonclick{position:absolute;top:0;left:0;bottom:0;right:0;width:100%;height:100%;border:none}.hidden{visibility:hidden}</style><script>function load_on_iframe(){document.getElementById("iframeonclick").setAttribute("onClick",""),document.getElementById("iframeonclick").className=document.getElementById("iframeonclick").className.replace(/(?:^|\s)hidden(?!\S)/g,""),document.getElementById("iframeonclick").src="PUT THE URL OF THE EMBED ELEMENT HERE, I.E. THE IFRAME URL"}</script>
If you still have any doubts or issues with this implementation, feel free to contact me via LinkedIn or send me a quick message on Discord.
Warning: Due to the misuse by users who would autoplay videos with sound on websites — creating a very poor user experience — it is no longer possible for a YouTube video to autoplay with sound once the YouTube URL is added to the SRC. Therefore, the user would need to click again either to watch the video or to play it with sound.
Whenever the iframe is not "above the fold" — that is, immediately visible to the user when the page loads — it is worth implementing lazy loading so that the iframe does not load until the user scrolls to it.
There are many ways to achieve this using JavaScript, but because it can now be done natively with HTML for the main browsers, there is no longer any need to load complex libraries just to implement this practice.
The way to do it is as simple as adding the loading
attribute with the value lazy
.<iframe src="https://example.com" width="600" height="400"
loading="lazy"
></iframe>
I wrote a more detailed article on this topic, which you can see here: lazy loading in iframes.
This is a meta tag that Google has supported since 2022, allowing content to be indexed when embedded via iframes on other pages.
This meta tag works if the page to be indexed has both a noindex
and an indexifembedded
. This will make the content non-indexable on the original page, but indexable on the page where it is embedded through an iframe.
It opens up some quite interesting possibilities, to which I will dedicate a full article.
Example of an iframe with an indexifembedded meta tag:
This curious meta tag has a useful, albeit somewhat niche, purpose.
Imagine you need to display some content on a website, but for whatever reason, the system of that website does not allow you to generate it directly. From another domain, however, you could generate that content and integrate it via an embed or an iframe.
In this way, the content would belong to the website containing the iframe, not to the original source.
For example, take this table with the Andalu-SEO certificates.
In reality, it’s an iframe — the certificates are generated on this site, but in this case, they are displayed on the Andalu-SEO website.
I currently offer advanced SEO training in Spanish. Would you like me to create an English version? Let me know!
Tell me you're interestedIf you liked this post, you can always show your appreciation by liking this LinkedIn post about this same article.