Discover how you can create custom iconography with the latest rendering modes in SF Symbols 3. We'll help you learn how to draw, edit, and annotate symbols, as well as explore more advanced techniques to improve the design process.
For a primer on working with custom symbol templates, we recommend first watching “Introducing SF Symbols” from WWDC19.
Hello, and welcome to WWDC. My name is Mike, and today we're going to walk through how to create a custom symbol that takes advantage of the new features introduced in SF Symbols 3. First, we'll recap what a custom symbol is and when you may want to use one. Custom symbols involve working with an SVG template. With SF Symbols 3, we have an all new template version, so we'll discuss the changes from previous versions.
We'll walk through how to generate templates, edit your symbols, and prepare them for rendering modes other than monochrome.
We'll cover annotation, the process of adding rendering mode data to your symbols.
We'll discuss some more advanced techniques that can drastically impact your workflows.
And lastly, we'll wrap up by covering exporting for Xcode and distributing your custom symbols. Let's get started. So, what is a custom symbol? Well, SF Symbols were introduced in 2019.
In the initial release, there were more than 1,500 symbols available to use in your apps. Since then, the library of symbols has only grown. Two years later, with SF Symbols 3, it totals over 3,000 symbols. Now, these symbols cover a wide variety of subjects and categories. But your app may have a specific need that isn't fully captured by an existing SF Symbol such as a teacup in a circle. This is where custom symbols come in.
If you need a custom symbol, you would draw it as a series of vector paths and place it in a custom symbol template. The template is in the SVG format, and includes your designs and some guides.
This template is the mechanism for your own symbols to take advantage of all the features that SF Symbols have to offer. This includes typographic alignment to make sure your symbols look good next to text, margins for making sure symbols are optically centered with one another when used in lists and table views...
Multiple weights to match text and adjust to features such as accessibility bold on iOS...
And lastly, three weight-matched scales to adjust to the context of different UI elements. So those are the highlights of SF Symbols and custom symbols. To review the basics of a custom symbol template, it's recommended to watch "Introducing SF Symbols" from WWDC 2019. To learn more about the design details behind SF Symbols, check out "What's new in SF Symbols" from WWDC 2021. Now that we know when to use a custom symbol, let's review the template that makes them possible. To go along with the new features in SF Symbols 3, there's a new version of the template, version 3.0. This version of the template has some important new capabilities compared to version 2.0, and it requires Xcode 13 or greater.
In 3.0, the left-margin and right-margin guidelines have more explicit names, indicating the design variant that they correspond to.
These margins, for example, have the suffix "Regular-M." This means that for additional control over optical alignment you can add margins to any variant in the template, and as long as they have a suffix matching one of the design variants, they will be respected.
More importantly, this format of the template is able to embed information on how a symbol should look in different rendering modes. We can embed data for existing modes, such as monochrome and multicolor, as well as data used by the new hierarchical and palette modes. On top of all of this, the 3.0 template supports some advanced functionality that can empower you to accomplish more by doing less. We'll talk about this in detail in the "advanced techniques" section. For the full specification of the new template, check out our updated documentation at Developer.Apple.com/SF-Symbols.
Now that we're familiar with the new template, let's work on a custom symbol. So I'm working on a card game app with some of my colleagues, and the SF Symbols app has us covered for a lot of symbols that we need. There are four suits as well as a stack that we can use to represent a deck of cards. The only thing missing is something we could use to represent the Queen of Hearts, which will play a special role in our app. I'm picturing a symbol of a crown with a heart on top. I can start by opening the SF Symbols app so I can customize an existing SF Symbol. This way, I'll have some point of reference for stem thickness, scale, and alignment. If I search for "crown" in the SF Symbols app, I notice that we have a nice, unfilled version available. This will be a great starting point. All I need to add is the heart on top.
I can select "crown," and from the contextual menu select Duplicate as Custom Symbol. And under the Custom Symbols section in the sidebar, there's now a cell for the crown I just duplicated. "Custom.crown" is a bit vague, so I'll rename it.
"Queen.heart" is much more descriptive of what I have in mind. Now, this is a good way to start a new custom symbol, but you may have some symbols from past years as 1.0 and 2.0 custom symbol templates. That's not a problem. You can drop the existing symbol on the app, and it will automatically get added to the current collection and up-converted to a 3.0 template.
Once the symbol is in my collection, whether I copied an SF Symbol, like "crown," or imported a custom symbol like "Teacup.circle," I can export it for editing in my design app of choice such as Sketch, Illustrator, or Figma. To do so, I can select File Export Template, or Command + E. This will export a 3.0 template in monochrome so that I can customize it.
For symbols that originate in the SF Symbols app, you have two options for the initial setup of your 3.0 template: static and variable. Which setup you choose depends on your design goals.
The static setup should be familiar, as it looks similar to a 2.0 template. There are 27 sets of paths and one set of explicit margins on regular in the medium scale. If you are targeting a particular weight and scale, or only plan on designing one or two variants of your symbol, this setup will work well. The variable setup, on the other hand, will generate a 3.0 template that has three sets of paths and three sets of margins. If you plan on supporting all design variants, you may be interested in starting with this setup, since it gives you the minimum number of design variants needed to generate the other 24. This requires that all your paths have a very high level of compatibility and consistency.
But don't worry about this now. We'll revisit these requirements and this setup of the template later in detail. For now, I'll export a static setup since I'm only going to draw one or two variants. With my template open in my design application, I'm ready to begin editing.
Like working with a 2.0 template, I can delete design variants I don't need and only design a few to start.
For templates that don't have compatible paths, Regular-Medium is still required, so I'll start with that.
I'll make room for the heart on the middle spire of the crown. And I want this symbol to look good in multicolor mode, so I'll adjust the paths so that I can assign colors to particular parts of my symbol later. With these adjustments, I now have a single closed shape for the hollow part of the crown. Next, I'll focus on the heart.
Now, as I edit my symbol, I may use strokes to match the stem thickness of Regular-Medium since I am working on a stroked symbol. This gives me flexibility as I iterate on the proportions and size of the heart.
But notice, I make sure to convert any live strokes to paths once I'm happy with the design. Converting to paths ensures that the stroked shapes can be filled with color later. Another benefit of converting to paths is that I can make some minor optical adjustments for when a stroke isn't precise enough. Like here, on the top half of the heart, the stroke is too large and round on the inside. Since I converted to paths, I can fine tune the curve to look less clunky.
Now that I have one design variant drawn, this is a good time to talk about some items to keep in mind if you want your symbol to support rendering modes other than monochrome.
Avoid using live strokes in the final design. Instead, make sure to convert any strokes to paths so that the resulting shapes can take on colors or hierarchy groups.
Avoid using open paths. These are paths that have a start point and an end point that do not connect. Since there's no closed fill area, these shapes will be unable to take on any colors. Instead, make sure all shapes in your design are closed with a defined fill area.
Avoid special fills involving more than one color such as gradients or effects like drop shadows. If these are present, they will override any multicolor or hierarchical data you create for your symbol. Instead, stick to standard, flat fills with no additional effects. Now, if we jump back to my design tool, the template is pretty bare.
I may want to add semibold so that the symbol responds to the accessibility bold feature on iOS. To do this, it's recommend to copy an existing drawing you have to the desired layer and adjust it from there.
This is a good habit to get into as it will result in the same number of paths being used across your design variants.
Preserving the number of paths across all design variants is a requirement if you want to produce a symbol with multicolor or hierarchical data.
In this example, I've colored the paths to indicate their number and order. Both design variants have four paths. The first two paths make up the folder, then we have a circle as the third path, and a plus sign as the fourth path.
As a result, these two drawings look great in multicolor.
These drawings also have four paths present, but, if you pay close attention, you'll notice I've shuffled the order of the paths on the right.
The main stroke of the folder is the first path in the drawing on the left, but the third path in the drawing on the right. When designs have the same number of paths but in different orders, they are likely to render very differently.
And if we were to render these drawings in multicolor, they don't match up. The green of the plus badge is being applied to the folder in the design variant on the right.
Back to the Queen.heart symbol. It looks great so far. And since I was careful in how I created my design variants, I can make it even better by annotating it to support multicolor and hierarchical modes.
Before I can do that, I'll need to import my symbol back into the app. I can simply drop it on the existing cell we have to update it in the SF Symbols app.
Now, you're not required to annotate your symbols, but if you want to control your symbol's appearance in rendering modes other than monochrome, it's a good idea.
To annotate, you'll use the individual paths that make up your symbol as your building blocks.
From these, you create a set of layers for each rendering mode. A layer is simply a collection of paths with some associated rendering data. Here I have a layer for the crown with seven paths, and a layer for the heart with two paths.
Layers in multicolor mode get assigned a color, and layers in hierarchical mode get assigned a hierarchy group.
Layers have an explicit z-order where the layers on top will block out the layers below. This is no different from creating layers in a design application. To begin annotating, I select my symbol in the app and enter the gallery view. In the inspector on the right, I can select the rendering mode tab so I can preview and annotate my symbol.
I can choose between monochrome, hierarchical, palette, and multicolor. When in a mode other than monochrome, you will be able to add and edit your layers corresponding to the active mode.
And in the center we have our preview. Here we can interact with all the paths we have at our disposal and assign them to layers.
I'll start with the multicolor rendering mode first.
I'll create a new layer for the crown.
Then, I can select a color for the layer. For multicolor layers, I can choose from various system colors, or use my own custom color. It's recommended to use system-provided colors whenever possible, as they will adapt to changes in the system's appearance to look great in light mode, dark mode, high contrast modes, and different vibrancy contexts. I'll use system yellow for the crown.
And that's one layer done. Now, just for the heart. I'll add that on its own layer in red.
I want to add a bit more depth to my crown in multicolor mode by setting colors on the hollow parts of my symbol.
A path can be used in any number of layers. So, to achieve a stroked and filled effect, I've added a layer with the paths that I want transparent and set it to a lower opacity.
I'll do the same for the heart as well.
That looks great. Next, I'll move onto hierarchical.
I can construct my layers like before, but instead of colors, I assign hierarchical groups ranging from primary to tertiary. The hierarchical data will be used in the hierarchical and palette rendering modes.
I'll add a layer for my crown in secondary.
And the heart in primary.
I can see in the preview that a bit of the crown shows through the heart where they overlap because the heart isn't fully opaque. This is a common problem when working with overlapping shapes.
To control how these overlaps get rendered, each layer has a toggle on the right.
If inactive, transparent layers will blend with the layers below, as shown on the left. This is the default behavior. If active, transparent layers will clear what's behind them and render as if the other layers don't exist, as shown on the right.
With the clear behind toggle set, now my symbol behaves as expected. The hierarchical annotation data also gets used by the palette rendering mode, so I'll make sure our layer interaction looks good there as well.
This looks great. The cyan layer is transparent but since clear behind is enabled, we can't see any of the indigo crown behind it.
In the palette rendering mode, I can assign two to three colors to my symbol, instead of just one like in hierarchical. Let's review the difference in how these two modes interpret hierarchical annotations to apply color.
Hierarchical uses one color and will apply it to your symbol's layers, varying the opacity based on the hierarchy level. In this case, we have a symbol with a primary group and a tertiary group. Palette takes two to three colors, and the behavior will differ slightly based on the number of colors passed. Passing two colors will distribute the colors among the available hierarchy groups regardless of their level. For this symbol, since we only have two groups, the first color is applied to the primary group and the second color is applied to the tertiary group.
If you pass three colors, then each one is applied to the corresponding hierarchy group. The first color is assigned to primary, the second to secondary, and third to tertiary.
If you need to continue editing a symbol you've already annotated, you would export a template and edit the monochrome representation in your design tool. Then reimport the symbol and verify your annotations still render as expected. Special care must be taken when modifying the paths of an annotated symbol if you wish to retain your annotation data. Since this data requires the same number of paths across designs, you can safely add, remove, and adjust points.
But removing or reordering whole paths will make your design go out of sync with its annotation data. In these cases, you will need to reannotate the symbol to account for its new path structure. Now, I have my symbol in two design variants, and it's annotated so it will look great in other rendering modes. I could stop here, but what if I need to support other combinations of scale and weight? In this section, we'll talk about techniques for working with custom symbols that can save you time if you plan on drawing three or more design variants.
In the past, I would continue filling out the rest of the variants in the template one by one, adjusting the paths to match the desired weight and scale. But now, with SF Symbols 3, there's a much better way to do this. If you provide just three design variants with compatible data, you get the rest of the template for free. This is the structure of the SVG you will get when asking for a 3.0 variable template. Let's dive into the requirements for producing compatible designs. First, we check for what we refer to as design sources. These are Ultralight-Small, Regular-Small, and Black-Small. If those are present, then paths are assessed across the sources to see if they match up. Let's focus on the Regular-Small source and the Black-Small source for a comparison.
Across design variants, all paths must have the same number and order exactly as we discussed earlier with annotation requirements. I've colored the paths of the crown here to indicate their order. There are nine paths, and they all match up.
For example, the two paths for the heart are the eighth and ninth path in both design variants. So far, so good. Next, we'll check inside the corresponding paths across design variants. Let's compare the outside path for the heart of the regular source and the black source. Each path is constructed from a series of points. We have 24 points for the regular source in red, and 24 points for the black source in blue.
To be compatible, points must match one-to-one between the corresponding paths. Each pair of matching points create an imaginary line, and moving each point along its respective line allows us to blend between the two compatible paths.
Since each point in the regular source corresponds to a point in the black source, we can do just that.
We'll focus in on the smaller heart in red and observe the path as it blends with the larger heart in blue.
Blending is what allows for a new path to be generated anywhere between the compatible paths. This blending is known as "interpolation." Now that we know how interpolation works at the point level, let's zoom out and apply it to the entire symbol.
You'll notice that any weight between ultralight, regular, and black can be computed.
This is the mechanism for the weight compensation necessary to generate the medium and large scale design variants for your symbols.
Let's recap those requirements. For a symbol to be considered interpolatable, it needs three things.
First, the three design sources. Ultralight-Small, Regular-Small, and Black-Small.
Second, path compatibility.
All paths must match between the sources. And lastly, point compatibility. All matching paths must have the same number of points.
So how would I go about making one of these interpolatable symbols? Well, instead of a static setup, I would start by exporting a 3.0 template from the SF Symbols app with a variable setup. This way, I have margins and outlines for the three source designs.
I would start with Regular-Small and add my heart on top, as we did earlier for Regular-Medium. This time it is just for a smaller scale.
Since interpolation has very strict requirements, it's recommended to get the initial Regular-Small design variant into good shape before working on the other sources.
When you do go to work on the Ultralight-Small and Black-Small sources, it is best to copy and paste the Regular-Small paths and only reposition the points from there.
This is critical to make sure your custom symbol is capable of generating the other design variants. So let's review that one more time.
When you want your symbol to be interpolatable, avoid adding or removing points, as this will break compatibility.
Instead, only adjust the existing points. Moving points and control points is fine, since this preserves the compatibility between designs.
Once ready, I can drop my updated template on my custom symbols cell in the app, and annotate it just like I did before. Since I was careful in drawing my sources, I have all 27 variants covered, and I'm all set to hand this off to get implemented. Now that we've covered ways to create your custom symbol, let's talk about next steps such as how to distribute your symbol.
When distributing your symbol, you have two options. You can export a 2.0 template or a 3.0 template.
2.0 templates should only be used if you plan on back deploying to an older OS such as iOS 14. It only contains monochrome so make sure your symbol makes sense when used in that mode.
Converting to a 2.0 template is a lossy operation. Annotation data and explicit margins are removed since the older OS will not understand them.
3.0 can embed all the multicolor and hierarchical data you've added, as well as any custom margins, but it is not backwards compatible.
Careful here, this template is not a source artifact for editing. Current design tools may not be entirely compatible with the embedded annotation data. If you need to make more edits to your symbol or share it with a colleague, it should be imported back into the SF Symbols app. From there, you can work on the monochrome representation without risk of dropping your annotations.
The 3.0 template that you export should go straight to Xcode or back to the SF Symbols app. If your minimum deployment target is iOS 14, you will need to export both a 2.0 and a 3.0 template and use the appropriate asset based on a version check.
If your minimum deployment target is iOS15 or later, you only need to export a 3.0 template.
If you are sharing a symbol with a colleague, export a 3.0 template. They can then import that into their SF Symbols app to continue editing and annotating. We covered a lot of content today, so let's do a quick recap. We talked about the new 3.0 custom symbol template, the features it supports, and how to edit it.
We covered how to prepare your symbols for annotation and add multicolor and hierarchical data.
We explored a more advanced workflow that opts into some stricter requirements to take advantage of interpolation. And we just finished talking about how to distribute your symbols.
Once you've delivered your symbols, they are ready to be used by the OS. There are some new APIs you can use for rendering your symbol in the appropriate mode.
To learn more about calling SF Symbols and custom symbols in code, check out "SF Symbols in UIKit and AppKit" and "SF Symbols in SwiftUI," both from WWDC 2021. That's custom symbols from start to finish. I hope you enjoy creating and annotating your own symbols. [upbeat music]
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.