documentcloud / documentcloud-pages

Responsively embed DocumentCloud pages.
https://documentcloud.github.io/documentcloud-pages/examples/
MIT License
23 stars 10 forks source link

iframes: why we aren't doing them now, and when we might #18

Open reefdog opened 9 years ago

reefdog commented 9 years ago

TL;DR: We plan to support iframes as soon as we are happy with an embed design that maintains a static aspect ratio.


This issue details our difficulty using iframes for our particular embed needs, and why we're punting on them for now. It's not impossible, just enough of a lift to move out of MVP.

A common request and a strong internal desire is for our embeds to be delivered via iframes. This has significant advantages: the iframe is a silo within which our JS/CSS are safe from the parent page (and vice versa), and as a single HTML tag it's generally portable:

<iframe src>

Wouldn't that be nice. Unfortunately, it's not responsive at all. This is usually solved with a little HTML wrapping and some CSS, so you end up with something like this:

<style>…</style>
<div class="iframe-wrapper><iframe src></div>

A little gross, but at least it doesn't require any JS on the parent page. Unfortunately, it only works if the embed maintains a static aspect ratio, like a video. For those with aspect ratios that could change while the embed is being used or resized, like ours, you have to whip out the JS:

<iframe src>
<script src></script>

What would this script have to do?

  1. Initialize responsiveness by injecting the necessary HTML/CSS for the above-mentioned method
  2. Maintain aspect ratio when a parent page resize/reflow causes the iframe to resize
  3. Listen to the iframe's child page for resize-triggering events and apply them to the iframe

That last one is the doozy and why Pym exists.


– begin aspect ratio tangent –

It's useful to ask: what causes us to have a variable aspect ratio? Why can't we calculate the ideal aspect ratio for a given resource when generating its embed code and force ourselves to keep it? Here's what causes aspect ratio changes:

  1. Notes: Our current page embed design can cause notes to pop out of the bounds of the page embed.
  2. Page navigation: Different pages within a document can have different aspect ratios. Embedding a single page can initialize at that page's aspect ratio, but if the reader navigates to a new page with a different ratio, the embed has to adjust.
  3. Interface chrome: While images can scale almost infinitely, interface chrome has reasonable usability bounds. So we have a static 40px-tall menu bar atop a page that's 400px wide and 760px tall. Total embed width:height is 400px:800px for an aspect ratio for 1:2. Now shrink the page to 200px wide and 380px tall; total embed is 200px:420px for an aspect ratio of 1:2.1.

There are design compromises for each of these problems; we just have to decide if they're worthwhile.

– end aspect ratio tangent –


So what are we going to do?

We'll start with the progressive enhancement model used by Twitter and others, where the initial embed code is effectively a noscript replacement plus some JS:

<div class="DC-embed-stub>
    <p><a href="…">Minutes from the 12/2014 meeting</a></p>
    <img src>
</div>
<script src></script>

The script then parses the faux-noscript and replaces it with the real direct-embed markup.

When will we add iframes?

  1. When we design an interface that promises a static aspect ratio, or
  2. When we can do all of the following:
    1. Fork or enhance Pym to fit our progressive enhancement model (it currently appends to a div instead of replacing contents) and to not mind being embedded multiple times per page
    2. Provide a stable message-passing API atop Pym between parent and child
    3. Provide an initial iframe state that also acts as a noscript, or basically a non-responsive and potentially mis-aspect-ratioed representation of the embed, but which we are satisfied with as the worst-case fallback
anthonydb commented 9 years ago

Just going to drop the name Embed.ly here to note one of the places this came up recently.

reefdog commented 9 years ago

Edit: After re-reading Embedly's email to us, large portions of this comment may be incorrect. They may not be opposed to us sending markup/styling, just JavaScript. Which means we can deliver a responsive iframe-based response, it just can't have a dynamic aspect ratio. See https://github.com/documentcloud/documentcloud-pages/issues/18#issuecomment-143861472 for a summary.

Yeah, I nearly wrote a chapter on Embedly. They're a strange case. (They're also only an issue w/r/t our oEmbed endpoint, which shouldn't but can have a different embed strategy than the wizard.)

According to the emails we've exchanged with them and their own docs, they expect nothing from the oEmbed endpoint but an <iframe> tag. No wrapper, no styling, no JavaScript. They think it should be up to the consumer to then make that iframe responsive.

This means they are, by design:

  1. Opposed to us delivering a responsive solution via oEmbed, and
  2. Incompatible with any variable aspect ratio responsive embeds

I don't see how we can square our needs with theirs. We either have to satisfy Embedly by delivering a non-responsive iframe tag via our oEmbed endpoint (which forces all of our oEmbed consumers to handle responsiveness on their own and still doesn't allow for variable aspect ratios), or shrug them off.

knowtheory commented 9 years ago

Okay, so the problem is that we need to specify the aspect ratio at the time the iframe is inserted/defined.

By the time a document is done processing, we should know the aspect ratio of the document and the individual pages (this is another tick mark in favor of storing the individual aspect ratios of pages and making them available).

At that point, a document or page can be embedded either through automatic means (say an oembed request) or manually by a user requesting an embed code and saving that in their CMS.

In the first case, we have full control over the definition of the iframe and it would be possible to specify what the height/width/aspect ratio for a document should be. (note this is a change with non-trivial consequences as it would require making a database call in order to identify the max|min|avg aspect ratio)

In the latter case, we would only have one shot at getting the aspect ratio right if we were to bake that information directly into an embed code and handing it off to the user. That means that if the document were modified, the aspect ratio would not be updated. That said, our current embed codes do not codify that information directly (except at the user's request). And it might be viable to continue doing that.

reefdog commented 9 years ago

I would love if we could depend on the aspect ratio at load time remaining static. But see the "aspect ratio tangent" section. It would require some heavy design compromises; I'm totally willing to explore them, but with our existing design, our aspect ratio will change during use.

I'm fully in support of calculating/storing individual page aspect ratios. Even if we never lick the above, it's still useful in generating sensible default dimensions for the embed code.

reefdog commented 8 years ago

Summary of our options:

<iframe src>

:x: Responsive :x: Dynamic aspect ratio :white_check_mark: Pleases Embedly


<style></style>
<div>
  <iframe src>
</div>

:white_check_mark: Responsive :x: Dynamic aspect ratio :white_check_mark: Pleases Embedly


<iframe src>
<script></script>

:white_check_mark: Responsive :white_check_mark: Dynamic aspect ratio :x: Pleases Embedly