Models

If you like to generate the type system programmatically from your SASS stylesheets, or you are just curios, this section will give you a glimpse into the models used to calculate font size, line height and letter spacing. So here they are:

  • Font Size
  • Line Height
  • Letter Spacing

Font Size Models

Modular Scale

The piano scale model, used for the font size, is inspired from Tim Brown's work on music-like type scales. The difference is that here we are using intervals from an equal tempered piano, which is the modern way of tuning. Tim's model is based on the just intonation piano tuning, which is using whole numbers ratios; this is one of the classical ways of tuning. Since the classical tunings are actually approximations, I've chosen the more precise modern system.

Piano keys

The equal tempered tuned piano model works as following: We have an octave interval (which means doubling), and we have 12 piano keys for each octave. If we consider the keys are in a geometrical progression, we need to find the 12th root of 2 to find the semitone (the interval between 2 consecutive keys) value. The semitone is also known in music as minor second.

semitone = nthroot(2, 12) = 1.059463094 = 1.06 minor-second = semitone = 1.06

Once we have the semitone, we can successively multiply with it to find the other intervals values. Then we can calculate the tone (major second in music), as following:

major-second = tone = semitone * semitone = 1.12

Using the same approach, we can calculate the rest of the intervals.

minor-third = major-second * semitone = 1.19 major-third = minor-third * semitone = 1.26 perfect-fourth = major-third * semitone = 1.33 tritone = perfect-fourth * semitone = 1.41 perfect-fifth = tritone * semitone = 1.50

Now we have all the intervals we need for font sizes calculation. But for a concrete type system we need to pick one interval, for example major second. The font sizes in a type system are also in a geometrical progression, therefore we will get the values by successive multiplication with the interval, starting from a chosen base font size.

size(n) = size(n-1) * interval

Sizes smaller than the base font size are calculated by successive division with the interval.

size(n) = size(n-1) / interval

Metric Scale

The font size model, used for the metric scale, was reverse engineered from the type scales fond in some major design systems. The popularity of these type scales made me curious to extract and to propose the model, as a way to generate font sizes multiple of a scale unit.

The modular arithmetic progression model, used to calculate the font sizes, works as following: We can imagine an arithmetic progression which increases its step every number of items, this number of items is actually the module. So each consecutive module in the progression use a slightly bigger step. In this way we can have values which are multiple of a scale unit, and in the same time we get a kind of nonlinearity in the model. This is important, because we need a model which can express hierarchy in the type system. Here we have the scale generative model.

size(n) = size(n-1) + step + a

Basically a specific font size is get by adding something to the previous font size. As we expect, this looks like a plain arithmetic progression, plus a new term "a". This new term does the magic, by adding a value which is increasing for each successive module. And this value is added to our step. Now we need to find "a" as a dependence on the module size and the step. And it looks like the following:

a = INT((n - 1)/mod-size) * step

And if we are replacing "a", with the expression above, we have our final model, used to generate our type scale.

size(n) = size(n-1) + (INT((n - 1)/mod-size) + 1) * step

If we are expressing the step in units, for example the step can be equal with one unit, we have:

size(n) = size(n-1) + (INT((n - 1)/mod-size) + 1) * unit

Sizes smaller than the base font size are calculated by removing the unit from the previous size. Since there are only few sizes under the base font size, we can use this simplified model here. Therefore there is no need to decrease the progression step after a number of items.

size(n) = size(n-1) - unit

Line Height Model

The line height is calculated by multiplying the font size with a ratio. This line height ratio is dependent on the font size and the line width. It looks that we need to calculate the line height ratio for any combination between the two variables (font size and line width). The good news is that we can keep the line width fixed, then we calculate only based on the font size. Actually when we are choosing our font size and the line height base, we are implicitly considering a decent line width.

Then we need a model that can calculate all the line height ratios (for all font sizes) starting from a base font size and a base line height ratio. Therefore all resulting line height ratios will be relative to these two base values. This means that a change in these base values will propagate throughout the type system, which is exactly what we want to achieve.

Note: The line height is also dependent on the font family, but we take this in consideration when we are choosing the base values. In that order we can view these base values like a hint we are providing to the model.

In years of experience, and after some research work, I've found that a reciprocal model is a perfect fit for our problem. The inspiration was taken from the pendulum motion where the frequency is the reciprocal of the period. The model looks like the following.

line-height-ratio = 1 + a / font-size

Now we can find "a" if we want the model to go through the coordinate point (base-font-size, base-line-height-ratio) as following:

a = (base-line-height-ratio - 1) * base-font-size

And now if we are replacing "a", with the expression above, we have our final model, which we can use to calculate all the line height ratios for the entire type system.

line-height-ratio = 1 + (base-line-height-ratio - 1) * base-font-size / font-size

Finally we can calculate the corresponding line heights, by multiplying font sizes with the line height ratios.

The Backward Method

Our reciprocal model used to calculate line heights has an interesting particularity, which can be easily demonstrated. It happens that if we calculate the difference between a line height and its corresponding font size, then we add this difference to any font size in the scale, we will get line heights which are satisfying our model. In that way we are applying our model backward. And because its simplicity, this backward method is actually very powerful. We can also perform the calculation using our brains, without any calculator. Here is our backwards simplified model.

line-height = a + font-size

The question is how we can find the "a" value, which will be added to every font size to get the corresponding line height. Since we are choosing the base font size and line height, "a" can be easily determined.

a = base-line-height - base-font-size

And if we replace "a" in the initial model will get our final model.

line-height = (base-line-height - base-font-size) + font-size

And of course, we can calculate the corresponding line ratios, by dividing line heights with the font sizes.

Letter Spacing Model

Letter spacing is dependent on the font size, more precisely it decreases as the font size gets bigger. Similar with what we have for the line height, we need a model that can calculate all the letter spacings (for all font sizes), starting from a base font size and a base letter spacing.

Note: The letter spacing is also dependent on the font family, but we take this in consideration when we are choosing our base values. Similar with the line height, we can view the base values like a hint for the model.

It looks like the reciprocal model is also a good fit for us here, but this time with a different twist.

letter-spacing = a / font-size - 3

Now we can find "a" for which the model will go through the coordinate point (base-font-size, base-letter-spacing).

a = (base-letter-spacing + 3) * base-font-size

And if we replace "a" in the initial model will get our final model.

letter-spacing = (base-letter-spacing + 3) * base-font-size / font-size - 3

The model will calculate the letter spacing in percents (relative to the font size). If we want to use "em" units, we can adjust the model accordingly.

letter-spacing = (base-letter-spacing + 0.03) * base-font-size / font-size - 0.03

And that's pretty everything we need to set up a precise type system for a modern digital product. The benefit of this model driven approach is a cohesive and scalable type system achieved in record time. I wish you good luck in adopting the tool and the models, as a part of your daily design life.

End image