richiejp logo

Responsive IFrame

Intro

This isn’t about embedding a YouTube video which seems to be the majority of articles on this subject. I have made a availability calendar web app which adapts to the screen size.

My first user has a Wordpress site and wants to embed it on a page. The options for doing this are:

  1. Reimplement the availability calendar frontend in Wordpress.
  2. Inject the HTML and JS without an IFrame.
  3. Use an IFrame

Option one is not a bad idea in general, but I don’t like PHP or React. I also don’t want complicated interactions between Open and closed source.

Option two is horrendus. Mashing JS and CSS together from online sources results in non-reproducible behaviour. I also have a relatively strict content security policy on DoBu.uk and hooks to report errors.

Finally there is IFrame. The main advantage of which is near total isolation. Which is also why it causes trouble.

Fixed size

If your IFrame content is a fixed size, then you don’t have an issue. Just set the width and height to the content size.

Below is the availability calendar iframe forcibly set to the width of an iPhone X/XS (according to Firefox). The height is the minimum required to display the calendar without scrolling.

I’ll quote the HTML to save you opening dev tools.

<iframe
    title="Availability and booking calendar"
    width="375px"
    height="600px"
    src="https://dobu.uk/availability/richiejp?no_header&no_footer&min_scroll=640&new_tab_enquire"
>
</iframe>

The only styling applied to this is by Bulma’s “minireset” which removes the default border.

Usually at this size DoBu.uk would still allow scrolling (see dobu.uk/availability on a phone). However with the min_scroll=640 query param, the interface switches to a fixed height view when the width goes below 640px.

This prevents scrolling within the IFrame when the IFrame is taking up most of the screen width. My present opinion is that scrolling within an IFrame is OK if there is space around it. Otherwise it messes up the UI.

Note that, in general setting the width and height attributes to an absolute value is a bad idea. These should be set to 100% and the dimensions controller by the enclosing element with CSS. Even if it is a fixed size because it is consistent with most other elements.

Resizing

My IFrame content has mobile and desktop versions (i.e. it’s responsive). What would be worse is if it’s content can change size and you want the IFrame to take the size of its content.

We have two basic cases

  1. Resize the IFrame to fit the screen size or orientation.
  2. Resize the IFrame to fit its content.

So far I have avoided needing to do the later. Due to security, finding the content size of an IFrame is a pain. It requires setting up a communication channel (e.g. window.postMessage if available).

The former can be done entirely with HTML and CSS. Below is a reactive IFrame.

The HTML is still very simple

<div class="dobuuk-availability">
<iframe
    title="Availability and booking calendar"
    width="100%"
    height="100%"
    src="https://dobu.uk/availability/richiejp?no_header&no_footer&min_scroll=640&new_tab_enquire"
>
</iframe>
</div>

Now the CSS excluding properties set by minireset.

.dobuuk-availability {
    height: 600px;
    width: 100%;
}

@media (min-width: 768px) and (min-height: 1080px) {
    .dobuuk-availability {
        height: 70vh;
    }
}

.dobuuk-availability iframe {
    border: 1px solid #e2e8f0;
}

On small screens the height is set to 600px. On larger ones we set it to 70% of the viewport height.

The media queries provide a heuristic for when there is enough space around the IFrame for inner scrolling. This requires tweaking, but the basics are there.

Possibly there are other tricks we could apply as well. For instance snapping to the IFrame when it gains focus.

However I think it is best to keep as much complication as possible on the side of the thing being embedded. This makes it easy for someone to embed DoBu.uk. In particular if they have a strict CSP or other restrictions on JS.