Prototypr

Prototyping, UX Design, Front-end Development and Beyond 👾 | ✍️ Write for us…

Follow publication

Shaping up your Framer prototypes with SVG

The newest release from Framer, Design, is a foundational step in creating an all-in-one interaction design tool. With Design, simple shapes can be created and manipulated visually, rather than imported from Sketch or Figma. And the best part: the elements and layouts made in Design are completely responsive by default.

The shapes we can make in Design are still somewhat limited: only rectangles and ovals. While this fulfills the bulk of our UI needs, occasionally our designs will require more complex shapes— icons being the most ubiquitous. This means that, for now, we still need to incorporate bringing in assets as part of our workflow.

We still have the ability to import from another graphics tool, but Framer accomplishes this by importing the relevant layers as pixel-based PNGs. If we want our entire prototype to be as responsive and crisp as what we’ve created in Design, we want to move away from pixel-based graphics, making this workflow problematic.

The case for SVG

Enter SVG (for Scalable Vector Graphics), a graphics format based on vector definitions. If you’re not familiar, Peter Nowell’s “How Designers Should Think About SVG” is an excellent place to start. In the context of our workflow, SVG is capable of preserving the same level of editability and control that we’ve come to expect from layers created in Design.

When we use SVG rather than pixel-based graphics, we have a much better idea of what our image consists of. Instead of only knowing the discrete color of every pixel, we have information around individual layer contents and hierarchy. Rather than just viewing the icon as an ambiguous rectangle, Framer can look within an SVG to target relevant elements.

Importing SVG into Framer

Exporting SVG assets can be a tricky process in and of itself, but once you have it exported from a graphics program, there’s a number of different ways to include it in your Framer project, which I’ll walk through next. Depending on the method, Framer can structure it within the code differently, which has significant implications for how you’re able to work with the SVG.

Via the Icons Panel

Framer has already laid the foundation for an ideal SVG workflow — included in Design is an Icon Management panel. All of these icons are constructed with SVG, wrapped within a Framer layer.

Unfortunately, only the Material Design icon set is included in this panel at this time, but I would expect iOS icons to be added very soon (as well as a way to manage your own icon set!)

Once we’ve included the icon, we’ll switch to code, where we can add a simple event that will update the heart’s color on tap.

heart.onTap (event, layer) ->
@.style.fill = "#FF7744"

Above, we are changing the color using the CSS fill property. This method works because the icon is ‘clean’, meaning there is no explicit fill property defined anywhere in the SVG. This is important, because if there are more specific fills defined within the SVG, they will overrule any CSS properties applied to the parent Heart layer. Here is the actual SVG code that constructs the heart icon:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"></path>
</svg>

All of the icons within the icons panel are clean, so this method will work for any of them.

Custom Icons with Drag and Drop

While there’s a few different ways to bring in icons of your own design, not all of them will afford you the same flexibility and control to edit and animate.

In Design mode, we can drag and drop an image directly onto the canvas. If the SVG has been cleaned, the icon should behave similarly to if you added the icon from the Icon Management panel. (You’ll usually have to go in and manually do this after export.) If the icon has been cleaned up correctly, styling properties like Fill and Shadow will work as expected for any other shape created in Framer.

If we switch gears over to Code view, we can still drag and drop in our SVG assets, but Framer is constructing the layer a bit differently. Here’s the code that’s generated when we drag an image into the code editor:

Apple = new Layer
width: 156
height: 177
image: "images/Apple.svg"

If you’re familiar with CSS, this is the equivalent of using SVG as a background-image. This is a simple method to default to, if you just want an icon that will scale cleanly across your responsive prototypes. But by referencing the SVG file as an image, we lose visibility and control over its “innards” that will let us accomplish anything complex with interactivity or animation.

Inline SVG

To maintain that visibility and allow for full-on interactive icon wizardry, inline SVG is our most powerful tool. Rather than a separate image asset for Framer to reference, inline SVG keeps all of the file information right in the document. We can use inline SVG in Framer by pasting the SVG code right into the HTML of a layer. We’ll enclose it within triple quotes, so that single quotes, double quotes, and line breaks won’t break the string.

inlineHeart = new Layer
x: Align.center
y: Align.center
backgroundColor: null
inlineHeart.html = """
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"></path>
</svg>
"""

To get the code above, open up your exported SVG in any text editor, or right click the layer in Sketch and select “Copy SVG Code”. Before pasting it into Framer, I almost always optimize the code with a tool like SVGOMG.

If we look back to the icons created in Design, we can see that those are set up using inline SVG as well. You can open up the Web Inspector to examine the layer hierarchy more closely, or just run print goodapple.html to see the specific vector glory.

I still typically manually create the layer and add to the HTML, because it gives the most visibility into the SVG contents. This method also allows the SVG file to be mutable, so the icon can evolve with the rest of my design.

Sometimes, especially with more complex icons or illustrations, inline SVG can become a gigantic code blob. If I’m sick of looking at that, once I’m done working with the SVG-specific part of the prototype, I’ll save the SVG as an external file. We can bring the external file into our project (while keeping it as inline SVG) with the domLoadDataSync Framer utility.

apple.html = Utils.domLoadDataSync("images/apple.svg")

Targeting Inline Elements

The demo below demonstrates the more granular control we have over our image with inline SVG. Follow along with this section by downloading the full prototype.

First, we create a few layers in Framer: the background layer and the layer which will house the grape icon. We’ll show how beautifully SVG scales by defining its size relative to the width of the screen. The background circle will be a fourth of the size of the screen, and the Grapes layer half the size of the circle. Then, in the SVG definition, I’ve set its width to 100%, to always follow along with its Grapes container layer.

BG = new Layer
width: Screen.width/4
height: Screen.width/4
x: Align.center
y: Align.center
borderRadius: Screen.width/8
Grapes = new Layer
width: BG.width*.5
height: BG.width*(.5*(189/144))
Grapes.html = """
<svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 144 189">
...

Rather than just changing the fill for the entire image, we’ll target multiple pieces of the icon. The most reliable way of targeting SVG elements in Framer is by using querySelector, where querySelectorAll() will return an array of any matching elements, and querySelector() a single, earliest-occurring instance. You can target elements by type, class, or ID. (ID is usually easiest, as it’s just what you named the layer in Sketch!)

GrapesArray = Grapes.querySelectorAll('circle')
Leaves = Grapes.querySelector('#leaves')

Similar to before, we update the properties of the elements on click. We can apply the same styling to all of our grapes by looping through the array generated by querySelectorAll().

Grapes.onClick (event, layer) ->    @.animate
scale:1.1
options:
time:.3
for grape in GrapesArray
grape.style.fill = "#B78CFF"
grape.style.fillOpacity = ".4"
grape.style.stroke = "#B78CFF"

Leaves.style.stroke = "#66BB66"
Leaves.style.fill = "#66BB66"
Leaves.style.fillOpacity = ".4"

Finally, to help demonstrate the responsiveness, we add an event listener for changes in the viewport size. On resize, we will reset the size and position of our circle and grape layers.

Events.wrap(window).addEventListener "resize", (event) ->

Next Steps

So far, we’ve focused on the basics of SVG and the possibilities for incorporating it into your Framer workflow. At a minimum, I hope I’ve made the case for SVG being your default image type, especially given the recent responsive developments in Framer. I’ve covered the very common use case of changing icon colors on click or tap, but this is only skimming the surface of what is possible! Next week, we’ll look in more depth at animation and some more complicated SVG effects. Thanks for reading!

This is a living document— please reach out with questions or if you feel there’s missing information surrounding the basics of SVG in Framer.

Finally, thanks to Jenn Chin and Material Design for the use of their icons.

Published in Prototypr

Prototyping, UX Design, Front-end Development and Beyond 👾 | ✍️ Write for us https://bit.ly/apply-prototypr

Written by Melissa Cameron

Product design @Stripe. Designer who codes, but only during the full moon.

Responses (4)

Write a response

as soon as there is an ID in the SVG and I am using them in a module it doesn’t work anymore. Framer tells me Error: Can not set html: There’s already an element with id ‘b’ in this document’ Any advice how to fix this?

--

When is your next article coming? Can’t wait for it…

--

For inline SVG, you could also use ES6 template literal, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals
` your SVG code here `
and you will not need to worry about anything in between.

--