All guides

Make an iframe responsive

Set the iframe width to 100% and give it a shape with the CSS aspect-ratio property. For content with a changing height, such as a form, the framed page must send its height to the parent with postMessage. The parent then sets the iframe height.

5 min read · Updated

Pick the right method

An iframe does not grow to fit its content. The parent page cannot measure a cross-origin page, so you must tell the frame how big to be.

ContentMethod
Video, map, slide deck: fixed shapeCSS aspect-ratio
Dashboard or app that fills an areaFixed or viewport-based height
Form, article, widget: height changesThe framed page sends its height with postMessage

Fixed shape with aspect-ratio

Use this for a video or any content with a known shape.

<iframe
  class="embed"
  src="https://your-site.com/video/42"
  title="Product demo video"
  width="1280"
  height="720"
  allow="fullscreen"
></iframe>
.embed {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
}

Keep height: auto. The aspect-ratio property needs at least one automatic side of the box. If both width and height have fixed sizes, aspect-ratio has no effect. The width and height attributes stay as a fallback and give the browser the shape before CSS loads.

Older code wraps the iframe in a box with padding-top: 56.25%. All current browsers support aspect-ratio, so you do not need that wrapper.

Fill an area

For a full app, give the frame a height that follows the screen:

.app-frame {
  display: block;
  width: 100%;
  height: 80dvh;
  border: 0;
}

The dvh unit follows the visible height on phones, where the address bar shows and hides. Do not use height: 100% unless every parent element also has a set height. If one parent has no set height, the frame falls back to its default height of 150px.

Auto height with postMessage and ResizeObserver

You need code on both pages. The framed page measures itself and sends the number. The parent page checks who sent it and sets the height.

In the framed page (https://your-site.com)

const parentOrigin = "https://partner.example";

function sendHeight() {
  const height = Math.ceil(document.documentElement.getBoundingClientRect().height);
  window.parent.postMessage({ type: "embed:height", height }, parentOrigin);
}

new ResizeObserver(sendHeight).observe(document.documentElement);
window.addEventListener("load", sendHeight);

ResizeObserver runs the function each time the page changes size. This covers images that load late, accordions, and form errors.

Do not set html { height: 100% } on the framed page. Then the page is always as tall as the frame and never reports a smaller height.

In the parent page (https://partner.example)

<iframe
  id="booking"
  src="https://your-site.com/booking"
  title="Booking form"
  style="display: block; width: 100%; height: 400px; border: 0"
></iframe>

<script>
  const frame = document.getElementById("booking");

  window.addEventListener("message", (event) => {
    if (event.origin !== "https://your-site.com") return;
    if (event.source !== frame.contentWindow) return;
    if (event.data?.type !== "embed:height") return;

    const height = Number(event.data.height);
    if (Number.isFinite(height) && height > 0) {
      frame.style.height = `${height}px`;
    }
  });
</script>

The start height of 400px stops the layout from jumping while the frame loads.

Common mistakes

  • No origin check. Any page can post a message to the parent. Always compare event.origin with the exact origin you expect.
  • "*" as the target origin. The framed page then sends data to any parent. Name the parent origin, or use "*" only for data that is not private, such as a height.
  • A loop between the two pages. If the framed page uses 100vh or percentage heights, each resize makes it taller. Size the framed content by its content, not by the frame.
  • Frames on many sites. If the widget runs on many parent sites, you cannot hard-code one parentOrigin. Pass the parent origin in the iframe URL, and check it against a list on your server.

For more on safe messages, see Talk to an iframe with postMessage.

Test it on a real page

Paste the URL of the framed page into the iframe tester first. A responsive layout does not help if the page cannot load in a frame at all.

To see the frame on a phone, a tablet and a laptop side by side, use the responsive preview. The embed code generator writes responsive iframe code for HTML, React, Vue, Svelte and Astro.

Sources

Check your page now

Know before you embed.

Free, no sign-up, nothing stored. Paste a URL and get a verdict, a live preview, and the fix.