Is there a way to lazy load an embedded iframe? (Google Maps/youtube video)

I have youtube and google maps iframes on a website, which load immediately and hurt Lighthouse scores a lot. Any ideas?
66 Replies
MarkBoots
MarkBoots12mo ago
<iframe src="..." loading="lazy"> is already there for most browsers. Only FF is a bit behind, but I think they are rolling it out in the next release (december 19th?) https://caniuse.com/loading-lazy-attr
suhaylmv
suhaylmvOP12mo ago
it still loads a lot of js on page load
suhaylmv
suhaylmvOP12mo ago
No description
suhaylmv
suhaylmvOP12mo ago
No description
suhaylmv
suhaylmvOP12mo ago
Here's the website I'm working on if you want to test it out yourself https://www.amigosdelretiro.com/
Tu Lugar Favorito para Jugar al Ajedrez en Madrid - La Cabaña
Unete a cientos de personas que vienen cada dia para disfrutar de nuestras actividades, jugar al ajedrez y participar en torneos
ἔρως
ἔρως12mo ago
how about you only initialize google maps when the container is visible? you can use an intersection observer for this
vince
vince12mo ago
Also it's saying your 3rd party code (google maps) is blocking the main thread, and suggests to only load after your page has finished loading. So try using the defer or async attributes on your google scripts
ἔρως
ἔρως12mo ago
thats also a good solution i would use defer
suhaylmv
suhaylmvOP11mo ago
I'm so sorry for not responding @ἔρως @vince , with the new betterdiscord theme I can't see any changes on posts now I found a way to enable notifications on posts. didn't know about that earlier How can I do that? It's just an iframe, there aren't any google scripts
MarkBoots
MarkBoots11mo ago
remove the iframe src, and add it after the page load
suhaylmv
suhaylmvOP11mo ago
can you elaborate? how do I add it after the page load?
MarkBoots
MarkBoots11mo ago
in your script (with defer) you can select the iframe element and set the src
const iframe = document.querySelector("iframe");
iframe.src = "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3387.566481098533!2d-3.685281591511207!3d40.413765905744626!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd42289ffa59b9c7%3A0x514c9aebb4ecd4d!2sLa%20Caba%C3%B1a.%20Asociaci%C3%B3n%20Amigos%20del%20Retiro!5e0!3m2!1ses-419!2ses!4v1702800521259!5m2!1ses-419!2ses"
const iframe = document.querySelector("iframe");
iframe.src = "https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3387.566481098533!2d-3.685281591511207!3d40.413765905744626!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd42289ffa59b9c7%3A0x514c9aebb4ecd4d!2sLa%20Caba%C3%B1a.%20Asociaci%C3%B3n%20Amigos%20del%20Retiro!5e0!3m2!1ses-419!2ses!4v1702800521259!5m2!1ses-419!2ses"
vince
vince11mo ago
very cool, never thought of that what's the benefit of that though when you have loading=lazy? That would defer it, so wouldn't setting the src manually be redundant?
MarkBoots
MarkBoots11mo ago
loading lazy could be useful for other iframe content than googlemaps. don't know what is happening exactly with lazy load, but maps has a lot going on in the url params
vince
vince11mo ago
ah so you're saying that loading=lazy might not be enough to totally defer the maps call, so it's better to defer it manually inside a script essentially?
MarkBoots
MarkBoots11mo ago
i guess so. but I didn't deepdive into it. This just came up to me as a quick solution
suhaylmv
suhaylmvOP11mo ago
it still loads content on every page load for me I also included a console.log in that script, and it executes on page load it doesn't happen to you right?
vince
vince11mo ago
Did you defer the script itself?
suhaylmv
suhaylmvOP11mo ago
<script defer>
const iframe = document.querySelector("iframe");
iframe.src =
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3387.566481098533!2d-3.685281591511207!3d40.413765905744626!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd42289ffa59b9c7%3A0x514c9aebb4ecd4d!2sLa%20Caba%C3%B1a.%20Asociaci%C3%B3n%20Amigos%20del%20Retiro!5e0!3m2!1ses-419!2ses!4v1702800521259!5m2!1ses-419!2ses";
console.log("arst");
</script>
<script defer>
const iframe = document.querySelector("iframe");
iframe.src =
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3387.566481098533!2d-3.685281591511207!3d40.413765905744626!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd42289ffa59b9c7%3A0x514c9aebb4ecd4d!2sLa%20Caba%C3%B1a.%20Asociaci%C3%B3n%20Amigos%20del%20Retiro!5e0!3m2!1ses-419!2ses!4v1702800521259!5m2!1ses-419!2ses";
console.log("arst");
</script>
like this: in astro
ἔρως
ἔρως11mo ago
no, add it with an intersection observer defer doesn't do anything for inline scripts
vince
vince11mo ago
I was wondering about that, cool ohh that would be good too
ἔρως
ἔρως11mo ago
no no, it would be perfect the iframe doesn't load until the user scrolls to it
vince
vince11mo ago
what if the user has a bad connection and they scroll to it and instead of it popping up quickly it takes 10 seconds to load? I know with google fonts you can preload it; can you do the same with google maps (without the performance hit of loading it all at once on page load)?
ἔρως
ἔρως11mo ago
then it is a google problem, not yours it's just google maps you can preload google fonts, but you also can use display: swap or whatever the property is, for the page to keep going and then swap the text with the newly downloaded font and if you don't host the fonts yourself, you're in violation of the GPDR but seriously, if it takes 30 minutes to load, it's fine just add a spinner or something on top of it or under it
vince
vince11mo ago
if only it was this simple 😂 spinner/loading animation is a good idea though
ἔρως
ἔρως11mo ago
spinner solves the issue
suhaylmv
suhaylmvOP11mo ago
I think it works now!
<script>
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadGoogleMaps();
console.log("intersecting...");
observer.unobserve(entry.target);
}
});
},
{ rootMargin: "0px", threshold: 1.0 },
);

observer.observe(document.querySelector(".map-container"));

function loadGoogleMaps() {
let mapContainer = document.querySelector(".map-container");
let iframe = document.createElement("iframe");

iframe.src =
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3387.566481098533!2d-3.685281591511207!3d40.413765905744626!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd42289ffa59b9c7%3A0x514c9aebb4ecd4d!2sLa%20Caba%C3%B1a.%20Asociaci%C3%B3n%20Amigos%20del%20Retiro!5e0!3m2!1ses-419!2ses!4v1702800521259!5m2!1ses-419!2ses";
iframe.width = "100%";
iframe.height = "100%";
iframe.style.border = "0";
iframe.title = "Mapa de la direccion de la Cabaña";

mapContainer.appendChild(iframe);
}
</script>
<script>
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadGoogleMaps();
console.log("intersecting...");
observer.unobserve(entry.target);
}
});
},
{ rootMargin: "0px", threshold: 1.0 },
);

observer.observe(document.querySelector(".map-container"));

function loadGoogleMaps() {
let mapContainer = document.querySelector(".map-container");
let iframe = document.createElement("iframe");

iframe.src =
"https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3387.566481098533!2d-3.685281591511207!3d40.413765905744626!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd42289ffa59b9c7%3A0x514c9aebb4ecd4d!2sLa%20Caba%C3%B1a.%20Asociaci%C3%B3n%20Amigos%20del%20Retiro!5e0!3m2!1ses-419!2ses!4v1702800521259!5m2!1ses-419!2ses";
iframe.width = "100%";
iframe.height = "100%";
iframe.style.border = "0";
iframe.title = "Mapa de la direccion de la Cabaña";

mapContainer.appendChild(iframe);
}
</script>
used a bit of help from gpt4 not gonna lie...
ἔρως
ἔρως11mo ago
that looks horrible but yes, that should work
suhaylmv
suhaylmvOP11mo ago
anything to improve?
ἔρως
ἔρως11mo ago
remove these lines:
iframe.width = "100%";
iframe.height = "100%";
iframe.style.border = "0";
iframe.title = "Mapa de la direccion de la Cabaña";
iframe.width = "100%";
iframe.height = "100%";
iframe.style.border = "0";
iframe.title = "Mapa de la direccion de la Cabaña";
suhaylmv
suhaylmvOP11mo ago
why?
ἔρως
ἔρως11mo ago
well, do you have a .map-container? or is it just the iframe thrown there?
suhaylmv
suhaylmvOP11mo ago
yeah
ἔρως
ἔρως11mo ago
well, you can (and should) size the iframe with css, to get the same effect you can add a css to apply the styles there to the iframe instead
suhaylmv
suhaylmvOP11mo ago
I removed the first 3 lines and it works the same I think not sure why I had that inside the iframe before I should leave the iframe title though nope, it broke I'll leave it as it is afaik iframes need width and height specified in attributes
ἔρως
ἔρως11mo ago
the title is absolutely useless for an iframe it breaks if you don't add the css for it but well, leaving the other 3 lines in isn't the end of the world
suhaylmv
suhaylmvOP11mo ago
isn't it useful for accesibility? or maybe SEO
ἔρως
ἔρως11mo ago
seo? no, google can't read the title from it accessibility? eh, never tested it, but i guess doesn't hurt
suhaylmv
suhaylmvOP11mo ago
ok thanks for helping me!
ἔρως
ἔρως11mo ago
you can change the margin to be a little bit on the inside, so the iframe loads when it is actually visible
ἔρως
ἔρως11mo ago
the iframe is loaded by javascript and javascript that detects the browser position for seo, use microdata or some other micro format
suhaylmv
suhaylmvOP11mo ago
Tu Lugar Favorito del Retiro para Jugar al Ajedrez - La Cabaña
Unete a cientos de personas que vienen cada dia para disfrutar de nuestras actividades, jugar al ajedrez y participar en torneos
suhaylmv
suhaylmvOP11mo ago
is there a way to set some margin to the intersection observer?
vince
vince11mo ago
I don't know if crawlers can index based off scroll, but I'm pretty sure they can "wait" for javascript content to load. I'd have to look into that
suhaylmv
suhaylmvOP11mo ago
so it loads the map a little earlier?
vince
vince11mo ago
dude the typography is really clean
suhaylmv
suhaylmvOP11mo ago
no idea
vince
vince11mo ago
great font choice
suhaylmv
suhaylmvOP11mo ago
thankss)
vince
vince11mo ago
yea I think it's the rootMargin property but I could be wrong
ἔρως
ἔρως11mo ago
if it uses an headless instance of chrome for it, it's possible, but very computational expensive yes, it is
vince
vince11mo ago
<script>
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadGoogleMaps();
console.log("intersecting...");
observer.unobserve(entry.target);
}
});
},
{ rootMargin: "0px", threshold: 1.0 }, // here
);

...
<script>
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadGoogleMaps();
console.log("intersecting...");
observer.unobserve(entry.target);
}
});
},
{ rootMargin: "0px", threshold: 1.0 }, // here
);

...
ἔρως
ἔρως11mo ago
yup, that's what i was talking about you should optimize your images the cover image is massive in images, you have 1.1mb our of 2.1mb for your website
vince
vince11mo ago
Also your cover image uses .avif which isn't supported in all browsers iirc, be careful with that
ἔρως
ἔρως11mo ago
and the scroll is absolutely horrible on desktop you do have a few bugs with the animations personally? i hate these annoying animations with shit flying all over
vince
vince11mo ago
I like it but I think the site is a little bit too simple and I feel like you're using animations to make up for it. You have really good typography and color scheme going on though. Anyway offtopic lol
ἔρως
ἔρως11mo ago
don't think the typography is the best for this section but the map, well ... it works, but you only have a gaping hole there and you don't put the gps coordinates there by the way, use the more semantically correct <address> element as well: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address
suhaylmv
suhaylmvOP11mo ago
can you explain more in detail? totally agree, I was thinking a lot about this, but couldn't come up with anything at the end to make the design more rich I hope with time I'll come up with something you mean the beige section?
vince
vince11mo ago
i've been thinking a lot about this site lately. i think they do a really good job of keeping it simple but making it interesting https://grassrootsonline.org/. maybe you can get some inspiration from it
suhaylmv
suhaylmvOP11mo ago
I don't understand thanks, I'll check it out
ἔρως
ἔρως11mo ago
the title yes you have the address, but not the gps coordinates
suhaylmv
suhaylmvOP11mo ago
why gps coordinates? ok.
ἔρως
ἔρως11mo ago
well, gps coordinates are important for people to put it into google maps and find the place and also for old-school people who don't use google maps, but have a perfectly capable gps that's ok-ishly updated
suhaylmv
suhaylmvOP11mo ago
it's a place inside a park in the middle of the city, please tell me how the fuck a person can prefer using a gps instead of a mobile phone
ἔρως
ἔρως11mo ago
old-school people
Want results from more Discord servers?
Add your server