Creating a Variable Font

by Rainer Erich Scheichelbauer

14 December 2020 Published on 8 March 2018

Variable Fonts open a whole new world of possibilities. Creating them is a breeze in Glyphs.

What are Variable Fonts?

If you have not read John Hudson’s excellent introductory article, stop right now what you are doing, and read it. No, really.

Done? Okay. So let’s set up a variable font in Glyphs, step by step. Here we go:

Step 1 Define axes

If we want to interpolate, we first need to set up a design space. The design space is a coordinate system defined by axes, much like the Cartesian coordinate systems we know from high school. Just that, instead of x, y, z axes, we have design axes that make sense for typography, such as Weight, Width, Slant, etc.

So, we go to File > Font Info > Font > Axes, and add an axis by clicking on the plus button:

Adding an axis
Choose File > Font Info, then, in the Font tab, click on the plus icon next to Axes, and a new design axis will be added.

In the axis entry that appears, pick the kind of axis that you would like. You can take any of the official ‘registered’ axes: Weight, Width, Italic, Slant, Optical Size, and a range of proposed new axes. Or, you can make up your own ‘private’ axis.

You can add almost any number of axes, each of them must have a unique four-letter axis tag. In this example, I will stick to one ‘registered’ axis, Weight, with the predefined tag wght.

Step 2 Set up masters

In the same File > Font Info window, switch to the Masters tab, and add masters with the plus button in the lower left corner of the window, or duplicate existing masters, very much like you would for a Multiple Masters project. In our example, we will add two masters, Light and Bold.

For each master, pick the following settings:

  1. Most importantly, set the axes coordinates for each master. In our example, set the Weight value, e.g., 50 for the Light Master, and 200 for the Bold Master. Many designers like to use the stem thickness as value for the weight axis value, but you can enter whatever you like, as long as the values are sufficiently different, so that Glyphs can calculate intermediate instances. In our example, we could calculate an instance at numbers between 50 and 200, e.g., 75, 120, 182, etc.

  2. Make sure you pick an appropriate master name for each master. In our case, I would say Light and Bold are good guesses. The master names are not exported into the final font file. They are important for your own orientation when you work in Glyphs.

  3. Optionally, pick a master icon from the Icon pop-up in the General section of each master. You can select from a range of lowercase n’s representing all sorts of weight and width combinations. You can also enter a glyph name at the bottom, and Glyphs will use an image of the respective glyph as master icon. Again, this is only for your orientation, so pick something that makes sense to you.

Okay, now we have the masters set up, we can add drawings in each master. Here we go.

Step 3 Draw compatible glyphs

To keep it short and simple, we will stick to an uppercase A for this tutorial. I draw the light A (Cmd-1) with a stem width of approximately 50 units:

… and the bold A (Cmd-2) with a stem 200 units wide:

Add anchors by choosing Glyph > Set Anchors (Cmd-U) or even better, holding down the Option key, Glyph > Set Anchors for All Masters (Cmd-Opt-U). Most importantly, keep all your outlines and anchors compatible between both masters, just as you would in a Multiple Master setup.

Step 4 Add predefined instances

Even though our font is variable, and we have an endless amount of instances already, we can still pick some spots in the design space and define them as instances for the font submenu. In File > Font Info > Exports, add as many of those predefined instances as you like. Simply add new instances with the plus button in the lower left, or Option-drag an existing instance entry in the left sidebar to duplicate it.

All you need to do in each instance is this:

Setting up the instances
  1. Set an appropriate Style Name: e.g., Light, Regular, Medium, Semibold, Bold, Extrabold in our example.
  2. Optional: you can pick a Weight and Width Class from the pop-up menu right below the Name. The downside: this will only apply to the correlating static font exports, and not be written into the variable font. Read more about it in the Naming tutorial.
  3. Pick appropriate design space coordinates for each of your axes. Read more about the distribution of weights in the Multiple Masters, part 3 tutorial.
  4. Pick a Style Linking. In the uprights, you leave these usually blank, only the Bold is the Bold of the Regular. And every italic is the Italic of its upright counterpart, e.g., Semibold Italic is the Italic of Semibold. Only the Italic instance is the Italic of Regular, and the Bold Italic is the Bold and Italic of Regular. Read more about it in the Naming tutorial.
  5. And I hate to break it to you, but most custom parameters do not work in an OTVar instance, especially ones that do shape post-processing, like most filters. If you have any of those in your instance, they will be blissfully ignored by the software. Why? Because they jeopardize outline compatibility.

Step 5 Add a Variable Font Setting

OK, so custom parameters do not work. Kind of makes sense in most cases. For example, of course you cannot have different glyph sets in different instances of the same variable font, duh. Makes sense because a glyph cannot (and should not) just disappear or reappear when you move your sliders. That is why Export Glyphs and Remove Glyphs parameters are ignored in the instances. And you will find similar logical reasons for other parameters.

But what if we could apply parameters to the whole variable font? Well, we can. From the same plus menu in the lower left corner, add a Variable Font Setting:

… and define all the things you want to define, like glyph subsetting with the Keep Glyphs parameter, or changing the OpenType features and classes with the respective parameters, or setting a different family name, etc.:

Step 6 Export and Test Your Variable Font

Choose File > Export and click on the Variable Fonts tab:

If you have the latest Adobe Illustrator, Adobe Photoshop (CC 2108 or later), or InDesign (CC 2020 or later), you can export into the Adobe Fonts folder, choose the font in the Character panel, and open the little slider pop-up to experiment with the Weight axis:

Alternatively, you can drop the font file in one of the amazing web pages that allow you to test fonts. My favorites are Roel Niesken’s great Wakamai Fondue, ABC Dinamo’s Font Gauntlet (which also lets you animate your variable font), and of course Laurence Penney’s Axis Praxis page:

Or, you install the mekkablue scripts and run Test > Variable Font Test HTML, which creates an HTML file next to the latest OTVar export, and opens the enclosing folder in Finder. So all you need to do is drag that into a browser:

Circumventing bugs

Adobe’s OTVar implementation is buggy. So, if the font does not interpolate properly in Illustrator or Photoshop, it may not be your font’s fault. Symptoms vary, but may include glyphs staying static and not reacting to slider position changes at all, or ugly small kinks appearing during slider movements, e.g., like this:

If that happens, you can try to set different start points in your outlines. We found that this sometimes helps circumvent AI’s rendering bug. In any event, if you see that the same glitch does not appear in the web browsers, it’s not your font’s fault. And it is best to send your font file to Adobe support, alongside an AI file containing a simple test case.

Update: In recent CC versions, these rendering issues have become very rare. Actually we have not seen any of these in CC 2021.

Another annoying implementation bug is sitting deep in Apple’s renderer CoreText. Offsets of components are miscalculated if the LSB is changing. Watch how the a behaves correctly, while the a-umlaut shifts more than it is supposed to do:

This affects all environments that make use of CoreText rendering, which include pretty much all browsers on the Mac. In that case, the best you can do is make sure that all composites are decomposed when you export. Best way to do this: Add a Decompose Components in Variable Font parameter to File > Font Info > Font > Custom Parameters. Needless to say, the resulting TTF will be much larger, and not fit for web use until Apple fixes the issue.

We reported the bug to Apple, but if you have a good case in your hands, please let Apple know as well.

Update: Apple fixed the problem. Make sure you have the latest dot update of macOS 10.13, or a newer macOS.

Another bug in Apple’s rendering: The Optical Size axis (opsz) is misinterpreted in Safari. At the minimum (leftmost) slider position, it shows the rendering for the maximum value. This only appears in Safari, not in other browsers. Again, please let Apple know.

Then, there is a rendering problem that is caused by the fact that variable fonts keep their overlaps. Not really a bug, but it may appear to your users as such. If the edge of a shape is drawn by two (partially) overlapping path segments, anti-aliasing will cause the edge to appear darker than the ‘clean’ edges that are drawn only by one outline:

The only solution for this is to rewire your outlines in such a way that the outer edge of your shape is always ‘clean’, i.e., drawn by only one path at any given spot. E.g. like this:

In the very most cases, you will be able to fix this by removing overlaps and subsequently opening corners or reconnecting nodes. Both functions, Open Corner and Reconnect Nodes are available in the context menu of a respective point selection: individual corner nodes for opening corners, and pairs of corner nodes for reconnecting.

The mekkablue script Paths > Rewire Fire helps you find nodes that need to be reconnected. It cannot find everything, but usually most of the cases that cause unclean edges like the ones shown above. What you want is the option that finds ‘nodes on top of line segments’:

Optional: add a virtual master

Imagine you need an axis which only applies to some glyphs. Let’s say, the crossbar height, which is applicable to letters like A, E, F, H, but not S, D, J, O, etc., and not to any non-letters, like figures, punctuation and symbols. It would not make sense to draw a new master for all the font, would it? Rather, you would introduce an extra master only for those glyphs that have a crossbar. Well, for cases like these, we have something called a Virtual Master:

  1. In File > Font Info > Font, add a new axis to the Axes parameter. Since this is not one of the standard axes, names are arbitrary. In this example, I suggest the name Crossbar Height and the four-letter tag CRSB:

  2. In the same window tab, add a parameter called Virtual Master, and give it the value of the the Light master for the Weight axis, 50 in our example, and a minimum value for the Crossbar Height, let’s say zero:

  1. Go through all masters in File > Font Info > Masters, and make sure the axis coordinate for Crossbar Height is not zero but, e.g., 100. The idea is that the values make sense semantically somehow. In our case, zero represents the lowest possible crossbar position, and 100 the highest possible position. You can edit all of them at once if you select all the masters:

Now that the virtual master is set up in Font Info, you can draw the low-crossbar version of each glyph that needs it:

  1. Open the glyph in Edit view.

  2. In the Layers palette, duplicate the Light layer with the plus button. It will create backup layer carrying the current date and time as name.

  3. Right click the backup layer and turn it into an intermediate layer by choosing Layer Type > Intermediate Layer from the context menu:

  4. Double click the intermediate layer, and in the pop-up dialog that appears, set its design space coordinates for Weight (50 representing the Light master in our example) and Crossbar Height (0 representing the lowest crossbar position in our example):

  5. Now change the drawing to what the letter should look like with Crossbar Height zero:

Now the cool thing is: unless you want to do fine-tuning, you will not need to add a Brace layer for the bold master. In Variable Fonts the deltas (point movements) of the two axes compliment each other and can be added up to form the bold with the low crossbar. So the best strategy may be to see if it works with just one master, and only add additional ones if the result is not good enough.

That’s it. Now all you need to do is export, and try the font again in Illustrator, Axis Praxis or the Variable Font Test HTML script, et voilà: a second axis is available, for lowering the crossbar towards the baseline:

Effectively, we have added a second dimension to our design space. If you do that, it is advisable to keep the masters in a rectangular arrangement, or even better yet in a vertical or horizontal offset in respect to the origin master. In our example, the Bold master is horizontally offset towards the Light master (difference in the first coordinate only), and the master with the low crossbar is vertically offset (difference in second coordinate only). This way you have the most control because you can reach any point within the design space rectangle by simply adding the vertical and horizontal deltas you created by arranging your masters as described.

Optional: setting a different origin

Only one set of outlines is stored in the font. Non-OTVar-capable software will only be able to display these ‘default outlines’. That default is usually your first master. You can pick a different default, though. To do so, go to File > Font Info > Font or to a Variable Font Setting in File > Font Info > Exports and add a custom parameter called Variable Font Origin. As its value, pick the name of a master from the pop-up menu:

Yes, it must be a master. If you want any of your instances to be the origin, you would need to add the instance as an additional master: In File > Font Info > Exports, select the instance you want to define as your origin, open the Plus button in the lower left corner of the window, and pick Instance as Master from the pop-up menu that comes up. Now you have an additional master in File > Font Info > Masters, and you can set that as your Variable Font Origin.

Two things to consider:

  1. Default Appearance: One of the founding ideas behind variable fonts is that you can pick your most used instance as the default, typically the Regular. In Multiple Masters, you designed the extremes of the design space (i.e., your least used instances) and would interpolate everything in between. A variable font can go the opposite direction: it only stores the most important outlines, somewhere in the middle of the design space, and all other instances are derived from that one. So, for desktop fonts, pick the Regular as origin, or whatever the user will expect as the ‘default appearance’ of your font family. If all else fails, this is the weight the user will still be able to use.

  2. File Size: Picking a middle master will likely increase the number of your point deltas, and therefore, also increase the eventual file size. On a single-axis setup, it will likely double the number of deltas, if not more. In other words, for webfonts, it makes more sense to pick one of the masters in an extreme end of the design space, because you want to keep file sizes and load times down.

Optional: axis location

In File > Font Info > Masters, you can add a parameter called Axis Location. With it you can change the master’s coordinate on the axis. This makes sense if you need different values to be exposed to the users than the interpolation values entered in masters and instances.

In our example, you could argue that a Weight slider going from 50 to 200 does not conform to the spec because the values have to relate to the usWeightClass scale that goes from 1 to 1000. What’s more, all hundreds have a meaning, ranging from 100 (Hairline), via 400 (Regular) and 700 (Bold) up to 900 (Heavy). So in our case, the Light master corresponds to a 300 (Light) weight class, and our Bold master is more like an 800 (Extrabold) weight class.

What works and what does not

Some things you may have gotten used to, do not work quite as you may expect them to in a variable font.

  1. I briefly mentioned above that all post-processing with custom parameters in File > Font Info > Exports is ignored because they are too likely to break outline compatibility or glyph set consistency. That includes filters and the Rename parameters.
  2. Corner and segment components work. But they work differently: in variable fonts, they have to be applied before interpolation, whereas in a classic Multiple Master setup, they are inserted afterwards.
  3. Both intermediate and alternate layers work.
  4. Alternate layers do not translate into composites. There is a script solution for that though. See further below.
  5. Brushes work, as long as they are applied the same way in all masters.
  6. Path offsets do not reliably work currently. The translation into TrueType curves may break outline compatibility.

Not really optional: STAT table

In new fonts, including all Variable Fonts, naming info is stored in the STAT table. STAT is short for Style Attributes, and includes, among other things, information about axes, instances, and something called the display strings, or name strings: These are names for sections on an axis. E.g. a weight axis may be sectioned into Light, Regular, Medium, Semibold, Bold; a width axis into Condensed, Regular, Extended.

The idea behind this is that an application can name a user’s current instance, no matter what his or her slider settings are. Effectively, in a multiple-axis setup, you get n-dimensional fields of possible names. E.g., if your font has a weight and a width axis, you get columns of weights, and rows of widths, like in the table below. And in order to name the combination of a weight in the Bold section with a width in the Condensed section, an application can simply combine the display strings, and ta-daaa, we have ‘Bold Condensed’:

A display string is deemed elidable if it is left out when combined with other display strings. Usually this is the case for default-style names like ‘Regular’, ‘Normal’, or the like. The semibold weight combined with regular width is usually just called ‘Semibold’, not ‘Semibold Regular’; or the normal weight in combination with the italic style is simply called ‘Italic’, not ‘Regular Italic’. Thus, the display name ‘Regular’ is considered elidable.

Usually, Glyphs takes care of this pretty smartly by analysing the names of your predefined instances. If however, you find that in the STAT table entries, the display strings are not properly stored in the file, you can take control with these two parameters in File > Font Info > Exports:

  • Style Name as STAT entry: Takes the instance style name as combinable display string for an axis range. As value, use the four-letter axis tag to which the display string applies. Use this only in instances that are non-normal on one axis and normal on all others. That is because the normal attributes have elidable names and do not appear in the style name (e.g., ‘Semibold’ or ‘Condensed’). Example: In the Light instance, use this parameter with the value wght, because Light is a value on the weight axis.

  • Elidable STAT Axis Value Name: Declares the instance style name as elidable for the axis specified in the parameter value. As value, use the four-letter tag of the respective axis. Typically, you will add this parameter in the regular style, and you will add one for each axis for which the name is an elidable display string. Example: An instance called Regular has two Elidable… parameters, one with wght and one with wdth as parameter values.

Axis Mappings

One more thing about axes. Obviously, axes start somewhere and end somewhere. In a user interface, the beginning and end of an axis can be (and usually are) represented by the leftmost and rightmost positions on a slider. Everything in between, of course, is spread out evenly between these extremes. In other words, in order to display 25% of the interpolation, you put the slider at the quarter position, for 50% of the interpolation, you put it exactly in the middle, and so on. Makes sense, doesn’t it.

Wait a minute. Does it really? Giving it more thought, it really only makes sense if the instances that the user should be able to access are also spread out (more or less) evenly across the complete slider range. For the sake of the argument, let’s imagine a situation where the important positions are crammed in a small part of the slider range, and a large part of the slider is not doing much for the user.

This actually happens to be the case for the Weight axis (axis tag wght). In (almost all) weight interpolations, the various weight styles are not distributed evenly. Depending how thin the lightest master is and how fat the boldest, you will have more styles grouped together at different ‘focal points’ along the axis. For instance, interpolating from very thin to a ‘normal’, not-too-extreme bold will have styles concentrated towards the light end of the slider:

Why? Because in principle, equidistant movements of the slider correspond to the same changes in units, no matter where on the slider you make the movement. E.g., a certain back-and-forth here changes the design by 10 units, and the same back-and-forth there also changes by 10 units. However, adding 10 units to the stem thickness is a lot for a Hairline, which has only a few units to start with. But the exact same amount is practically negligible for a Medium or Semibold, because in comparison to the stem thickness, it is just a small change.

It is the other way around, if you go from a not-too-extreme Light or Book or Regular on one end towards a very bold Ultra Heavy on the other end of the slider. Now, the styles gather at the bold end of the spectrum:

How is that possible? Well, actually it is the reverse situation to the above, because what changes this time is the white in the letters. For a very, very heavy design, adding or removing 10 units to the white is a lot because there is so little white left. Yet, in the ‘normal’ range of weights between the average Book and Semibold designs, we still have the same situation: the styles are further apart.

Putting one and one together, it is now clear that interpolating from very thin to very bold usually has style concentrations towards both ends of the spectrum:

But on the other hand, the users do not care about our distribution problems, do they? For the users, accessing the different styles works best if they are distributed evenly across the axis, like this:

In other words, we need to somehow translate the evenly distributed user-accessible positions to the appropriately distributed design positions, like this:

This is called an axis mapping. We map what the user sees on the axis, to what the user actually gets on the axis. And we can achieve such a mapping with an Axis Mappings parameter in File > Font Info > Font > Custom Parameters. But how do we set it up? Easy:

  1. Determine the extremes on your Weight axis, i.e., the positions of your lightest and boldest masters. For example, we have a project with a Light Master at 50 and a Bold Master at 200.
  2. Determine the number of instances across the Weight axis. In our example, let’s say we have six instances: Light, Regular, Medium, Semibold, Bold, Extrabold.
  3. Calculate the gap size between styles: divide the difference between extremes by the number of styles minus one. E.g: (200−50)÷(6−1)=30. (Minus one because between six styles, there are five gaps.)
  4. Calculate the evenly distributed user-accessible slider positions by starting a the lightest, and repeatedly adding the gap until we hit the boldest. E.g., Light=50, Regular=80, Medium=110, Semibold=140, Bold=170, Extrabold=200.
  5. Now add an Axis Mappings parameter in File > Font Info > Font > Custom Parameters and edit its values:
  • Choose the Weight axis in the left column, and add six mapping pairs with the plus button, one for each style.
  • In the left column, put in the evenly distributed user-accessible slider positions we calculated above.
  • In the right column, add the appropriately distributed design positions, or in other words, the actual Weight interpolation values from File > Font Info > Instances.

If you have done everything right, you end up with something like this:

Tip: Make sure you map the extremes to themselves. If you do not have styles positioned at the outermost extremes (in our case, Light at 50 and Extrabold at 200), add mappings there anyway, with the same values in both columns.

You can also switch the parameter to a visual display and fine-tune the axis mapping. Add additional mapping points by clicking on the lines between the dots. Select a dot to edit its coordinates at the bottom: user-accessible number on the left, actual design value on the right. Drag an existing dot up and down to change the design value.

Technically, what this does is create a so-called Axis Variations table a.k.a. avar. It ‘variates’ the axis.

Pro tip: The specification stipulates that the weight axis values should conform to the usWeightClass list of values, i.e. 100=Hairline, 200=Thin, 300=Light, 400=Regular, 500=Medium, 600=Semibold, 700=Bold, 800=Extrabold, 900=Heavy. To achieve that, all you have to do is correlate your master positions to these values, and use those values for the Axis Location parameter in File > Font Info > Masters. In our example, we would add an Axis Location parameter for the Light Master with Weight=300 (because it correlates to the Light instance), and one for the Bold Master with Weight=800 (because it correlates to the Extrabold instance).

Usually, axis mappings will only create subtle changes to the way your font behaves when you drag the slider from one end to the other. So, it will be hard to verify if everything worked out the way you intended it to be. Therefore we need a special tool to inspect the avar table. Luckily, Laurence Penney’s Samsa is such a tool: drag the font onto the page, and in the Axes inspector, turn on the Show avar option:

And then drag the slider to see the green arrow that indicates how the visible slider position (top) maps to the actual design distribution (bottom). You can get geeky extra information if you hover over the visualisation and wait for the tooltip to pop up:

To explain, the avar values go between −1.0, 0.0 and +1.0. Glyphs will usually put your interpolation between 0.0 and +1.0. In other words, in avar, your light master will correspond to 0.0, and your bold master to +1.0. For instance, the tooltip pictured above says that the current slider position 550.4 (at 0.562988... or 56.3%) to the actual design position 540.38 (at 0.550476… or 55%), halfway between Medium (500) and Semibold (600).

Useful scripts

In the mekkablue scripts collection (link includes readme with installation instructions), you will find a number of useful scripts for making your variable font work:

  1. Interpolation > Composite Variabler: Reduplicates alternate layers of components in the composites in which they are used. Makes brace layers work in composites too. E.g., if you have a lowercase g with a brace layer that switches from a double- to a single-storey design as it gets bolder, you need to reduplicate the bracket layer in the composites gcircumflex, gcommaaccent and gbreve. You will still need to decompose the bracket layers after running the script:

  2. Kerning > Zero Kerner: Adds group kernings with value zero for pairs that are missing in one master but present in others. Helps preserve interpolatable kerning in OTVar exports. Use this if you find that some kerning goes missing, especially kern pairings that only exist in some masters.

    Update: Zero Kerner should not be necessary anymore in Glyphs 2.6.5, builds 1300 and above.

Additional resources

Want to dig deeper and know more about Variable Fonts? We have a few links for you:

STAT table sample font: Plantago by Viktor Solt-Bittner and Schriftlabor.
Many thanks to Rob McKaughan for his commentary and advice on this tutorial.

Update 2018-03-16: Corrected some typos (thx Jeff Kellem).
Update 2018-06-22: Clarified wording for the example values (thx Karl).
Update 2018-11-20: Updated naming of Variable Font Origin parameter.
Update 2019-02-15: Added links for Font Gauntlet and Wakamai Fondue. Updated test script and browser support info. Added Circumventing Bugs.
Update 2019-03-13: Added Additional resources.
Update 2019-03-04: Corrected typos and replaced Variation Fonts by Variable Fonts of the Export window (thx Nathalie Dumont).
Update 2019-03-20: Corrected typos, replaced Add Instance as Master for Instance as Master, and modified link to Nick Sherman's V-Fonts (thx Nathalie Dumont).
Update 2019-10-23: Added Useful Scripts.
Update 2019-12-04: Added section about the anti-aliasing problem.
Update 2020-03-08: Added paragraph about Safari opsz bug, the hint about the Rewire Fire script, and Samsa to the resources.
Update 2020-06-14: Added Axis Mappings chapter, updated Useful scripts, added a GIF for the Safari opsz bug.
Update 2020-07-09: Minor change of phrase in the paragraph about the Rewire Fire script.
Update 2020-11-17: Partial adaptation for Glyphs 3.
Update 2020-12-14: Largest part and screenshots updated for Glyphs 3.