Embedding Figma Prototypes

@sirajchokshi

Table of Contents

  1. Embedding Figma Prototypes
    1. Prop API
    2. Designing Overlays
    3. Putting it all together
  2. Footnotes

I’m a huge fan of Figma prototypes. They have proven to be a great way to share interactions (rather than static designs) with peers and clients. Developers and clients often have trouble inferring interaction and animation from static designs since they don’t have declarative knowledge of UI design patterns1. Figma prototypes are a great way to bridge that gap with minimal effort.

A prototype of a spreadsheet modal. Try clicking the “Download” button.

Figma’s “smart animate” mode is particularly useful for prototyping animations. It essentially generates a tween2 between two artboards based on the position and size of the layers in each frame. Sometimes results are surprisingly good. While it tends to perform pretty poorly on complex animations, it’s great for simple interactions that do add polish to a design.

Embedding Figma Prototypes

Figma prototypes can be shared via a link, but it’s also possible to embed them in a webpage. It’s awesome for quick demos within a website or blog post without writing a lot of one-off code. MDX makes it even easier to embed Figma prototypes in a blog post.

There’s no great off-the-shelf solution for styling the embed, but Figma provides a couple options to hide their baked-in UI and iframe-ing in the prototype itself.

This is how an embed from Figma looks by default:

<iframe
  style="border: none;"
  width="800"
  height="450"
  src="https://www.figma.com/embed?embed_host=share&url=https://www.figma.com/proto/..."
></iframe>

Already, there are a few annoying things about this embed:

  • The iframe is not responsive
  • The Figma embed UI is too busy over the prototype

Prop API

If we’re embedding a lot of prototypes, it’s nice to have a reusable component that handles these issues. I wanted this component to:

  1. Be responsive to the container width
  2. Bring my own UI for metadata and controls
  3. Link to the original Figma file

Given the constraints, here’s the API I came up with:

type FigmaEmbedProps = {
  url: string;
  aspectRatio: number;
};

I’ll admit that having to provide an aspect ratio is pretty awkward, but it’s the only way to make the embed responsive. The content is not only cross-origin but rendered on a canvas inside of Figma’s app code, so aspect ratio inference is not possible.

Given the aspect ratio, we can calculate the height of the embed based on the width of the container.

As for getting a link to the Figma file, we can parse the url parameter to extract the file id and construct a link to the editor page.

function FigmaEmbed({ url, aspectRatio }: FigmaEmbedProps) {
  if (!url.includes("hideUI")) {
    // if the url is unopionated about hiding
    // the Figma UI, then hide it
    url += "%26hide-ui%3D1";
  }
 
  return (
    <div
      style={{
        position: "relative",
        height: "auto",
        aspectRatio,
      }}
    >
      <iframe
        style={{
          width: "100%",
          height: "100%",
          border: "none",
        }}
        // forward provided embed url
        src={url}
        loading="lazy"
      />
    </div>
  );
}
import { FigmaLogo } from "icon-library"; // not a real package
 
/**
 * Extract the file id from a Figma prototype url
 */
function extractFileURL(url: string) {
  const regex = /proto%2F(.*?)%2F/;
 
  const match = url.match(regex);
  const id = match?.[1];
 
  return id;
}
 
function FigmaEmbed({ url, aspectRatio }: FigmaEmbedProps) {
  const fileId = extractFileURL(url);
 
  if (!url.includes("hideUI")) {
    // if the url doesn't is unopionated about
    // hiding the Figma UI, then hide it
    url += "%26hide-ui%3D1";
  }
 
  return (
    <div className="figma-embed">
      {fileId && (
        <a href={file} target="_blank">
          <FigmaLogo />
          Open in Figma
        </a>
      )}
      <iframe src={url} loading="lazy" />
    </div>
  );
}

Designing Overlays

I wanted to create a floating link to the Figma file and have it positioned over the prototype itself. This link needs to always be readable, and we don’t know what the background of the embed’s artboard will be until runtime.

There are a few solutions to this problem, but I decided to use CSS mix-blend-mode and background-blend-mode to maintain contrast. Most of the time the link will be over a pure color, so difference and darken work well to provide basic readability and a background for a hover state.

.figma-embed {
  position: relative;
 
  /* ... */
 
  a {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 1;
 
    mix-blend-mode: difference;
    background-blend-mode: darken;
 
    color: white;
    background: transparent;
 
    &:hover {
      background: #121313;
    }
  }
}

Putting it all together

Here’s the final React component made to fit with the rest of this site:

Footnotes

  1. There is also a productivity boost, even without this context loss. I am usually developing my own designs, but even with Framer Motion, I just find it easier to iterate on flows and interactions with prototyping animations in Figma.

  2. A tween is a type of animation that interpolates between two states. For example, a tween between two artboards might move a layer from one position to another. Read more on Wikipedia.