Dynamically sizing iframe to it's content

We’re running looker on our own infrastructure,  I have an embedded dashboard which talks to the host through the looker embed-sdk.

I want to size the iframe to the size of the dashboard to prevent weird nested scrolling behaviour.

  • It doesn’t look like the messages from the dashboard via the embed-sdk include the page height.
  • Because of cross-origin rules I can’t just `iframe.height = iframe.contentWindow.document.body.scrollHeight;`

Is it possible to;

  1. Include / receive the page height from the events already emitted from the frame?
  2. inject some javascript into the embedded dashboard frame so that I can emit my own event?
  3. Determine page height some other way?
Solved Solved
0 2 3,236
1 ACCEPTED SOLUTION

Hey there!

Nice thinking on making the embed experience cleaner with the dynamic height change. It sounds like the page:properties:changed JS event might be helpful for the use case you’re describing. This event outputs the height of the dashboard,  so picking it up from the iframe should allow you to edit the height of the iframe to line up!

There’s some great context on what the exact format looks like in the list here, which covers all the events that are sent out or receivable by the iframe: https://docs.looker.com/reference/embedding/embed-javascript-events#page:properties:changed

View solution in original post

2 REPLIES 2

Hey there!

Nice thinking on making the embed experience cleaner with the dynamic height change. It sounds like the page:properties:changed JS event might be helpful for the use case you’re describing. This event outputs the height of the dashboard,  so picking it up from the iframe should allow you to edit the height of the iframe to line up!

There’s some great context on what the exact format looks like in the list here, which covers all the events that are sent out or receivable by the iframe: https://docs.looker.com/reference/embedding/embed-javascript-events#page:properties:changed

I've been searching on and off for weeks for what I can only imagine is something every developer who is embedding Looker dashboards in their own framework wants to do: set the height of the Looker embed dashboard dynamically so the scroll bars don't show and the iframe is integrated seamlessly into your application. Why this setting is not set by default and why there is no documentation on this is beyond me. Reading the few traces of information on this topic from obscure forum posts, I was under the impression I would have to set up some sort of event listener where the iframe would talk to its parent and communicate the height, wrangle with multiple CORS issues etc. I.e. a complete nightmare. In the end, by accident of fat fingers, the intellisense on the Looker SDK object revealed a function, also not documented anywhere on the internet as far as I can tell, called `.withDynamicIFrameHeight()`. I tried it out and it worked straight away. I hope this helps other devs in a similar situation that have been trawling the internet for this simple piece of information.

Full example of the code that creates the Looker embed below, this was in a Next js project, version 13.4:

async function embedder(
  element: HTMLDivElement,
  id: string | number,
  onConnect?: (dashboard: LookerEmbedDashboard) => void,
  onStart?: (event: DashboardEvent) => void,
  onComplete?: (event: DashboardEvent) => void,
  onSessionStatus?: (event: SessionStatus) => void,
): Promise<void> {
  const dashboard = await LookerEmbedSDK.createDashboardWithId(id)
    .withParams({
      // theme: "dev_theme", // When you want to preview a different theme, this should match with a theme in Looker > Admin > Themes
      _theme: JSON.stringify({
        show_filters_bar: false,
      }),
    })
    .appendTo(element)
    .on("dashboard:run:start", onStart || noop)
    .on("dashboard:run:complete", onComplete || noop)
    .on("session:status", onSessionStatus || noop)
    .withDynamicIFrameHeight()  // add this to remove scrollbars on Looker dashboard
    .build()
    .connect();

  onConnect?.(dashboard);
}