Streaming is available in most browsers,
and in the WWDC app.
Introducing SF Symbols
SF Symbols introduces a comprehensive library of vector-based symbols that you can incorporate into your app to simplify the layout of user interface elements through automatic alignment with surrounding text, and support for multiple weights and sizes. Learn how easy it is to adapt to different screen sizes and layouts, and improve the accessibility and localizability of your app. Get details on how to create new symbols for your specific needs that perfectly match the visual style of SF Symbols.
- Adopt the new look of macOS
- Make your app visually accessible
- SF Symbols 2
- The details of UI typography
Let's do this.
Hi, I'm Paolo, and later on, I'll be joined by my colleague, Tom here on stage. And we are here today to introduce you to SF symbols. Symbols play a very important role in interfaces. They are effective at communicating meaning.
They can indicate which items you have selected. They can be used to visually differentiate one type of content from another, and symbols appears in -- appear in various contexts throughout the system.
This creates a sense of familiarity throughout the user interface.
Symbols are used in a variety of ways, and designing symbols comes with an inherent challenge, which is pairing them nicely with the other essential element of any UI, which is text.
Text is used in a variety of point sizes in the UI, and so are symbols.
We use symbols a lot, and so do you.
We want to make your job easier.
Now in iOS 13, we redesigned all our symbols.
You'll notice how the symbols have a rounder look, and how generally they are a bit heavier in weight, making them more visible. They're also designed to perfectly match and align with text.
And while we took great care in redesigning all the symbols in the system that you may already be familiar with, we are thrilled to announce that we've extended this list, and designed many more, which we call SF symbols. They are a platform-consistent, high-quality set designed by Apple for you to use in your apps.
They come in vector form, which means they are scalable, and will render great at small and large point sizes.
They come in weights that match our family of system fonts, San Francisco -- all the weights.
And there's over 1,000 to choose from. If these are still not enough, you can even customize them and create your own. Let's look at them in more detail.
They're designed to work with text. They're specified in typographic points, like text.
When symbols appear next to text, they all sit nicely on the same baseline.
When symbols and text are positioned vertically, there are two most common cases -- whether the text supports the symbol, or the symbol supports the text. Horizontal alignment ensures that everything looks great, and this is possible thanks to their margins, which are not necessarily the same, as you can see in the bottom-right blue rectangle. Margins are invisible, but they're always considered when laying out elements on the screen. Let's look at weights. SF symbols have been carefully drawn to look great at different weights, from ultra-light to black, just like our system fonts.
Every weight has been drawn manually, and special consideration went into each design. Thinner weights have a distinctive, beautiful elegance, while the heavier ones strive to maintain detail and visibility. There is a need for using symbols at different sizes when they are next to text, even if the text size doesn't change.
This is something that many of us already do, depending on the amount of emphasis that the symbol may need, and how much space is available.
So with iOS 13, we turned this into a system.
We call these scales -- small, medium, and large. It's important to notice here that the point size of the symbol is still the same. It's just the scale that changes.
Each scale remains weight-matched with the text, and, mind you, it's not just linearly-scaled, the stroke thickness is adjusted to the weight of the text, and the other great benefit is that using scales means that automatically they're optically vertically-centered to the cap height.
This way, vertical layout between symbols and text is automatic for all three scales.
So where are these scales used, and when should you use a particular scale? Well, here are 3 UI examples.
They all use 17-point text, but the container for each of these symbols have different heights. So the text is the same size in all 3, and the symbols are as well, but the symbols use a different scale in order to best fit their space. And in some places, like toolbars, your kit will do the right thing, and will pick the correct scale for the control automatically.
So when we put all this together -- resizing, scaling, and weight -- it means you can use them with dynamic type, and everything just works. And of course, symbols can be localized, too. Here's an example of the Voice Memos app, running in English, and running in Arabic. Notice how the time control reflect the numeral system of the locale. If you're wondering how to make sense of all these symbols, well, each symbol has a unique name, and most symbols come in variants that can be outlined or filled. They can be enclosed in a circle or a square, and may come with a standardized system of badges.
And we made it convenient for you to use these symbols.
First, they are included in the San Francisco fonts available for download, so you can use them in your design prompts.
The scales are accessible by open Type Features. The default scale is medium, and small and large can be selected through the Typography panel, or application-specific UI.
And as a reminder, these fonts are for design only, not for deployment. So how do you use these symbols? How do you access them and get them into your designs? Well, to help you with that, we created a new app, which is called SF Symbols, and this is what it looks like. It will let you browse symbols, either in a collection view or in a table view.
It will let you search them by name, and preview them in different weights that the fonts come in.
You can download the SF Symbols app with the new fonts from developer.apple.com/design, and speaking of design, design resources -- the new design resources on developer.apple.com also use symbols. They reference them by name, and some of the system icons are now symbols, too. So if you were using some of these, they will automatically use the new designs. Now that we've seen how to discover the symbols available to you, let's look at a real example. Here's a spec that you might have put together for your app.
You can see how before maybe you had to do something like this -- specify your images, the rectangular bounds, and explicit pad and insets, and now, symbols greatly simplify the paradigm. You just have to specify a name, its point size, and alignment, maybe its weight and scale if appropriate.
So I'm working on this app with Tom, and here the symbol in the second row is a bit too generic. It's a list of beverages, so I want to replace it with something more appropriate, something that conveys that these are tasty, hot beverages.
So I think I'm going to change it, and I want to go for a teacup.
That teacup looks great. I'm sure Tom will love it, but it's not included in the set of symbols that we provide.
Well, the SF Symbols app lets you customize and create your own symbols.
In order for you to do that, you need to start by exporting the symbol from the app, and symbols can be exported through their template.
This is what a template looks like.
It has all the weights, and all the scales for the symbol. The template is in SVG format, which means it can be edited by most design tools. It's specially constructed to be navigable and usable through any of the design stage, and the very same template is also directly used by Xcode as a source artifact.
No more tens of hundreds of files floating around.
So let's look at how we did our teacup. First, we went to the SF Symbols app, and we looked for a good starting point. Our teacup is enclosed in a circle, so I think the circle is a great starting point. And so, I searched for circle, and it's there. So I can select it and export its template from the File menu. I can save it, and now it's ready to be customized. I can open it in my editor and notice here how the layers have unique names. These names are important. They help identify each individual configuration of the symbol, the weight, and their scale, so you've got to be careful when you're drawing to make sure that your outlines are actually inside the appropriate layer. So I start my customization work, and I put my teacup inside the regular at the medium scale. I make sure that it's centered, and optically balanced, and then I scale it down, just for stroke thicknesses, and I put it in the small regular scale. And then I repeat the process, and I scale it up just for thickness, center it, make sure it's looking good for a large regular scale, and so forth until the template is complete.
At this point, I'm ready to export the SVG from the design tool. I can hand it off to Tom, and I'm sure he'll take great care of it. In fact, he doesn't have to do much. It's ready to be dropped in Xcode as-is.
So if you want -- don't want to provide all the weights for your symbol, you have to provide regular at medium scale at least, then the scales for regular.
Then same bold for the bold text feature, and if you want to support all dynamic-type styles, then include medium and bold as well. Of course, you should take into consideration the typographic palette of your app. You may need thinner or heavier weights.
So to recap, we got to know a new library of symbols that match San Francisco.
They are vector-based and come in different weights and scales.
You can browse them through the SF Symbols app.
We saw how to use them in your specs, referenced them by name, and how to specify their positioning, and finally, you can customize symbols using the SVG template exported from the SF Symbols app.
Now, I'd like to invite Tom to the stage, so he can tell you all about how to use these symbols in code. Thank you, Paolo.
Well, I'm really excited, and the first thing I would want to do is see if I can use one of these symbols in my own apps. And I have this simple slideshow app, and it has some UI that allows you to change the speed. But I'm really not very happy with these images. They're very basic, so let's see -- they're a good candidate for changing, and let's see what it does if we have a symbol in the Symbols app. So let's fire up SF Symbols, and search for tortoise, because maybe we can use the classic style tortoise and hare.
Turns out, there is one, so I can use this. That's great.
And the hare is there, too. Perfect. Now, how do I use them? It's very simple. We're introducing new API called UIImage(systemName that works very similar to the existing APIs. You just pass in the name you copy from the SF Symbols app, and that's it. If we build and run -- wow, bam, that looks amazing, and it was just two lines of code. Perfect. Now, Paolo sent me a spec, because we're working together on this app, and he really has to stop putting hot Belgian chocolate there, because now I really feel like hot Belgian chocolate.
But he gave me this spec, and it looks very different than the one that I got before. It's -- there's less information. I like that. That's less work for me, but let's focus on this image, because there's a new teacup there. He also gave me a file, teacup.svg file that I need to import into my asset catalog. Well, it's definitely a teacup. There's a lot of them. He really put some effort into it, and that's what I like about Paolo. He has, like, great attention to detail.
So now, my image is there, and I can just use UIImage(named to get to my teacup. If we run this, I get this. This is a real nice and sharp teacup, exactly what I wanted, but I'm not sure if you have noticed, when I imported the file, there are now two teacups in my asset catalog. It turns out you can now have two images with the same name, but they are -- have a different type.
So let's step back for a moment and explain what's happening. We're going to use envelope, because the teacup is not a good example.
Up until now, UIImage(named was pretty straightforward. You have an image in your asset catalog, and you can get it out using the API.
Now, with symbols, it becomes more complicated.
You can actually have an image with the same name, and there might be three versions of it. You might have a system symbol with this name. You might have a custom symbol with the name, and your old non-symbol image might still be there. For system images, there's no problem.
They're in a separate name space, because there's a separate API for them. And so they are -- there's no conflict there. It also means you can never get a custom symbol using this API, and you can never get a system symbol using the UIImage(named API. They are totally separate. For custom symbols, it's a little bit different. We prioritize things now, so we'll first look for a symbol image. And if we can find one, we will return that, and otherwise, we'll look for a non-symbol image, and then you get that back. Now, you might say, "Well, that's really annoying, because what if I want both?" But there's a good story for this.
With the same line of code, I can run my app on iOS 12 or earlier, and I get the old image, the bitmap image in this case. And if I run my app on iOS 13 or later, I get the symbol image. So I don't have to write any version-checking code to get a different image for the different OSs. Just provide 2 images with the same name, and it works out of the box.
If you do want to use the old image on iOS 13 or later, you have to duplicate or rename it.
So let's -- going back to our slides, and one other thing that we have is the configuration on this teacup. It should be large.
How do we do this? We create a new type that we introduced, SymbolConfiguration, and we create one with a large scale. The other configuration properties that are on the object are unspecified. We only have a large scale here, and then we can use the imageView to display our image. There's a new property on UIImageView called preferredSymbolConfiguration that will tell the imageView to use this configuration to render a symbol image. It will have no effect on non-symbol images. If we run this, what a difference a scale makes.
Now, you can also use this configuration to change the size of a symbol. You specify a point size, and optionally, a weight or a scale. Now, an important point here is that symbol point sizes are not screen point sizes. Symbol point sizes are expressed as font point sizes. They're typographical in nature. The screen point sizes describe the dimension of the image, the width and the height. Now, a picture says 1,000 words, so let's see that and visualize this. Like, we have this -- our circle symbol next to the "Favorite" text, and they are both specified using the system font at 28 points. Now, you might expect this image to be 28 x 28 points. Well, it turns out, it isn't, and these values are the actual correct values for this symbol at this configuration. And the image is not even square, and it's a circle. So for symbols, you have to let go of describing the image using a dimension. You have to use the symbol points, and you can think of it as a piece of text. Because if you have a piece of text, you describe it using the font point size, and not using its dimensions. It's the same. Another way to configure a symbol is using a text style, and that means that the symbol will behave according to the dynamic text style rules. It will behave the same as a piece of text with the text style.
So it matches great with text styles.
And imageView will automatically change the size of the image, and look up the right size at run time, depending on the preferred content size category of the app. You can see this in practice. Like, the text is nice and large, and the symbols scaled accordingly. And they have the nice -- the same weight.
So images can change size dynamically, and we have to talk about this, because you usually want to constrain an image by width and height.
And since a symbol renders always -- it's a vector.
You could be inclined to always specify this width and height, but it's actually not a good idea. First of all, it's not really correct. You can see on the screenshot that the symbol is described as a 17-point symbol, which is really small, but it still renders as a very large image, because the width and height are there. But you can also see that it's not entirely correctly centered. Like, it's a little bit off to the left, and a little bit off to the top. And secondly, it's not performance -- this is not the most performance way to display a symbol image.
So what you want to do is not constrain the symbol image at all, and have it be its natural size. In this case, we changed the size of the symbol to 500 points to match the size that we had before, and it looks a lot better, because it -- the centering is better than before, and the size is more correct.
This will also be more performance.
So if you do need a fixed size, set the point size, but otherwise have the symbol react to the symbol configuration, because even a large symbol configuration or a small-scale configuration may make a big difference for the size of the same symbol. Now, there's a lot of configurations here, and we've established that symbols are -- Paolo mentioned before that symbols are really made to work with San Francisco, our system font, but they work with any font. So you can use this API, SymbolConfiguration(font, to create a configuration that matches the font you give it, and it works with system fonts. It works with dynamic type fonts, but it also works with custom fonts. And especially for custom fonts, it will create a more high-fidelity configuration than the one you can create manually by copying the values from the font into your configuration. So it's better to use this for custom fonts. And when you already have a piece of text or a label that has a font configured, this is an easy way to create a configuration that matches that font.
And the last thing about configurations is that they are immutable. You can't change them. So what if you do want to change them? Well, you have to combine them. There's a method called applying, and it applies the specified configuration to the one that you're calling it on. So we'll take the configuration you're calling it on, and then take all the specified values in the other configuration, and override, or set them on the base configuration. And you get a new configuration that you can use somewhere else. But they are immutable, and the configuration themselves won't change.
Now, let's talk about layout.
We have this simple comments section in our app, and we want to expand a little bit for our next version, and also start using symbols here. And we have this avatar placeholder. I'm going to focus on just one row, and Paolo suggested switching to a new symbol. So let's try that.
That looks a lot better. So normally, if you would align images with a piece of text, you would use center alignment -- vertical center alignment, and in most cases, that would look like you would expect, and it would be the easiest. Now, for symbols, there's actually no difference. You can still use vertical center alignments, and it's actually preferred.
UIKit will actually take the typographic information in the symbol and use it to properly visually align the symbol versus the piece of text, and that might actually happen that the frames of the two elements are not matching up together. So the center is optically and not absolute, but you don't have to do anything. The system does it for you.
There's, of course, also cases where labels have more than one line, and vertical centering works great here, too. Same for symbols, we'll still use the typographical information to properly align for the center of the label. This is great for disclosure indicators, for example.
And looking back at our view, the disclosure indicator sits at the right place where I want it, but I actually want that avatar placeholder to be next to my first line. So let's move it. In this case, you can use baseline alignment, and up until now, it would be a bit hard to make this happen. You could do edge alignment, because you know the text and the label would be there, or you could do baseline alignment, but have to calculate offsets, so it would be weird. And in this case, for symbols, we can just baseline align, and that's it.
And you can actually inspect this baseline because we introduced a new property on UI Image called baselineOffsetFromBottom, and it expresses, like it says, the offset to the baseline from the bottom of the image. And it's an optional CG float. Why? Because not all images have baselines. Symbols come with one by default, but other images don't have one. So you have to check if the image has a baseline in order to see if you can use it.
In Objective-C, there's a separate method for it, because they don't have optionals.
Now, these baselines might be -- have unexpected values. In this case, we have two symbol images. They're right next to a piece of text. They have the same size, and they share the same baseline. But if we visualize their bounds, you can see that the chevron is sitting high above the baseline, and the cloud sits over the baseline.
And looking at their values, you can see that expressing the offset from the bottom means that going up is a positive offset and going down is a negative offset.
It also means that it's valid for an image to have a baseline that is outside of its bounds, in this case, the chevron.
And if you have a baseline value of zero, it doesn't mean that you don't have a baseline. It means that the baseline is the same as the bottom of the image. It's a bit surprising, but it works.
Now, the good thing is, we also added API to add baselines to images. You would use withBaselineOffsetFromBottom, and you would get a new image that has a baseline configured like you asked for. Again, this is an offset in screen points from the bottom of the image.
Now, the nice thing is, the image will start behaving like a symbol. It's not a symbol, but will behave like a symbol, because it has some typographical information. And so, you can use the same layout for symbol images as for regular images. You don't have to check does this image have a baseline? Then I use this layout, or the other way around, and this makes that a lot easier. And looking at our example, we now have actual avatars, and some rows without avatars, and it looks much better. And I only had to do baseline alignment for this first line. It's really easy.
I also want to touch briefly on horizontal alignments. You can see that the images are horizontally aligned on the same column, and you do this by specifying an offset that you want to align to, and then center the images on that offset. It's pretty easy. And then you can go from that offset to the text, or from the edge to the text. So you should actually center align, even horizontally, the images instead of applying a leading or a trailing constraint there.
Now, let's go back to our spec. What I wanted to say is that, like, by default, it's probably a good idea to start with center alignment, both horizontally and vertically. In most cases, that's what you want, and the system will handle everything for you. It will use typographical information if it's available, and otherwise, it will use the old-style just centering. And in this case, Paolo specified baseline alignment, because the second line -- the second item has two lines. So we'd need to use the baseline. Then we can fall back to baseline alignment, but that's also very easy. And this spec also properly specifies horizontal alignment of the images.
It makes the spec a lot easier to read.
Now, let's go back to buttons.
Buttons -- there's a lot of buttons in UIKit.
We have two types of buttons, system buttons and regular buttons. Let's start with the system buttons.
First of all, all buttons in UIKit come with a preset symbol configuration, and for system buttons, it's body large. That means that it reacts to dynamic type changes, has a body text style, and a large scale. Now, wouldn't it be great if you could create system buttons, like the info button in the available Wi-Fi networks list, but to create your own system buttons that looked exactly the same, with your own symbol image? Well, we thought it was a good idea, and we added some, an initializer on UIButton that allows you to create a system button with any symbol image. And it will behave like an -- like a regular symbol image.
Now, let's go to regular buttons. In this case, I have a pop-over, and they're used as actions in this view. And symbols really shine here. They're really in their place.
A regular button comes with a medium-scale preset.
Now, having said -- talking about these preset scales, what if you want to change them? Well, there's similar API on UIButton, as on UIImageView, called PreferredSymbolConfiguration forState. That works exactly like the other content accessors on UIButton. You can set a configuration for certain states. And it gives you maximum flexibility because you can set an image, you can set a configuration, or you can set both, and it will work perfectly.
Another button example is this one. It kind of shows what we mean with symbols and text really shine together, but it doesn't mean that they're always close together. These two buttons really belong together, and they're configured in the same way, both the left button and the right button. The preferred symbol configuration is matched with the font of that right button, and the only difference between the two is that the left one has a symbol, and the right one has a piece of text.
And you can see that they share the same baseline, and because their configuration is exactly the same, they also share the same metrics, and it makes layout a lot easier.
And to round off our button story -- I mentioned there's a lot of buttons in UIKit. We'll go to bar buttons. We have updated all the artwork in UIKit to use symbols. It not only applies to bar buttons, but everywhere, and bar buttons feel right in place with the new artwork. Now, if you do back-deploy to older systems, you have to keep in mind that if you create custom artwork, on older systems, you still get the previous, thinner artwork than the new, updated artwork. So keep that in mind if you create assets for your back-deployment.
You can use symbols in bar buttons with images. We have existing API for this, and you just put a symbol in there. And it will feel right in place with the system buttons. You don't have to do anything here.
That's all you have to do. And again, like regular buttons, bar buttons come with the preset configuration. And in any non-compact size class, like in portrait mode on your phone, the configuration will be large. If you then rotate your phone, and end up in a compact size class, we will change that configuration on the button to be medium. And this will call the symbol to slightly be smaller, and to fit perfectly in the more compact bars. It also means that you don't have to provide a secondary image anymore, because the system does all the work. It will scale using the built-in symbol scales. And on the iPad, we're -- we always have a large, because of the things I mentioned before. Now, another thing about symbols is rendering modes. Any regular image has, like, color data built into it, but for a symbol, it's different. It has an intrinsic mode. It doesn't have an intrinsic color. So we use the tint color to render the symbol, and if we don't have a tint color, we'll use black. But don't rely on that black, because it don't want -- work nice with dark mode, and it might be subject to change. How does this work? The rendering mode on any image is automatic, and up until now, for any image, that would usually resolve to always original. Now, in -- with symbols, that changes. Non-symbol images still usually resolve to always original, but symbol images will resolve to always template. And that means that we'll use the tint color to give them a color, and that's all there is to it. You can change the rendering mode on an image with the existing API.
Now, I've covered the basic UIKit controls, but sometimes, you do want to draw an image in a graphic context. And you would probably use draw(in Rect.
Now, for symbols, like I mentioned before, that's probably not a good idea, because they want to be their natural size. So it's better to use draw(at and have the image decide how large it wants to be.
But we have a problem. We have this image, but it's too small.
By default, images come with an unspecified configuration. Nothing is specified, and if we're just -- if you have to render it, and we don't find a specific value, we'll fall back to the system defaults. And in this case, that ends up with a pretty small image. Now, I can create a configuration to make it larger -- 34 points, and a bold weight, and then use new API withConfiguration to apply that configuration to the image, and get a new image with that configuration built in. Which results in this larger, slightly more bold teacup, which is exactly what I wanted.
Going back to our pop-over, Paolo also asked me to change the text here, because symbols feel at home in text. Can we replace some words with symbols? Well, we can, but symbols are typographic in nature, but they are still images. So we have to use an attributed string with an NSTextAttachment.
Now, this code will look familiar, but we have a new piece of API, NSTextAttachment(image that will create a text attachment with the image attached.
Now, this text attachment is a bit smarter than the regular one. It knows about symbols, and it will actually inspect the string around the symbol to complete the configuration of that symbol as much as it can. It will look at the font size. It will look at the font weight, but it will also look at the color, and then the completed image will be drawn.
The old API, or the existing API creating a text attachment and then assigning the image still works, but it won't get the matching behavior. And of course, you can also use this new API with any regular image.
Paolo also wanted some color here.
Yeah. And we created some new API to do this.
You can tint an image now. So withTintColor applies a color to the image, and it does so very efficiently. It will only render the color when it needs to, and then it will look at the most efficient way to do this.
And before, you would probably have to rasterize an image, and render into a graphics context, and then apply a color. You don't have to do that anymore. This takes care of this.
And it's especially important for symbols, because they don't have an intrinsic color, and this will give them a color. Now, symbols also have a different rendering mode. So if you really want that color to pop out, you have to change the rendering mode, and you can do it in one go with this optional parameter. Now, these two APIs are not in the first beta, but they will come soon.
So we've seen a lot of API, and we think we provided you with a great tool set to make your apps really shine in iOS 13. But there's a few tips. Prefer horizontal and vertical centering over edge alignment. It's a bit of a mental shift, but once you figure it out, it really works out.
And try to build your layouts from the smallest element up to the largest element. It's pretty easy to start with something small and then use it as a building block to make something larger. And be flexible. Image sizes can change. Allow your image views to be the size of their image but be aware of the fact that they can change. It can be at run time, or it can be over app launches, or even over system updates.
Caching images usually doesn't help.
It's a great source of bugs, and the system already does its best to provide the best performance that it can. And caching really gives you an override, so there's no need to do that.
And finally, rasterizing is, in most cases, the worst solution, or the least-optimal solution to fix the problem. So save your CPU cycles for something useful, and let the system rasterize an image. So try to avoid rasterizing images, especially symbol images.
The accessibility and localization sessions this morning were -- are very interesting to check out, because symbols make adaptation in those areas a lot simpler. And there's the Implementing Dark Mode tomorrow, where symbols also really shine because of dark tint color.
There are two labs you might be interested in. There's a text and SF symbols lab, and fonts lab on Thursday, and there's a design lab on Friday afternoon. And of course, you're welcome at any of the UIKit labs. Thank you so much for listening and enjoy the rest of your WWDC.
[ Applause ]
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.