In a recent project, I was required to add HTML page generated by external service into my next.js app. Usually, using Next.js for traditional HTML files is an overkill, but in our case, the whole application/website is written using Next.js. Only a small portion needs to be imported from out side.
At first I tried to look for a way to parse HTML directly so that I don’t have to convert it to jsx. Also, it was quite a large HTML document with styling and JavaScript. The solution turned out to be quite simple and straightforward. And this solution that I am going to explain you can be used for scenarios where you want to embed external web-page (make sure cross-origin is enabled). I ended us using an iframe
. I placed the HTML file as it is in the public directory and used iframe
as follows.
<iframe src="/test.html" width="100%"></iframe>
Pretty straightforward and simple. However, I wanted to share a few hacks with you that I used in this project.
Hack 1: Match iframe
height to the height of the content inside iframe.
This makes sure that there are no scrollbars, none of the content is hidden and it appears as if the iframe
is an integral part of the page. And this must work well when either the browser is resized or the container div
is resized — in our case, there are header, footer and navigation components in addition to the div containing iframe
on the same page and the navigation can be opened or closed. This is done by using event listeners on iframe.contentWindow
in useEffect
hook as follows:
useEffect(() => {
Array.from(document.getElementsByTagName("iframe")).forEach((iframe) => {
iframe.contentWindow.addEventListener(
"load",
() => {
const doc = iframe.contentWindow.document;
iframe.height = doc.body.scrollHeight;
},
true
);
iframe.contentWindow.addEventListener(
"resize",
() => {
iframe.height = iframe.contentWindow.document.body.scrollHeight + 40;
},
true
);
});
}, []);
Cool! The iframe
is the part of our document now. But still there was an issue remaining. The document used dark theme and the content in the external page used white background.
#javascript #nextjs