Advanced Usage with Typi

Last week, I wrote a tutorial to show you how to use the mixins and functions of Typi, a library I’ve created for responsive typography. There’s a lot more to Typi that I can cover in one article. So, this week, I’m going to show you some advanced tips that I use with Typi so you can use them as well.

You’ll learn:

  • How to output em media queries with Typi
  • How to use Typi with the Modular Scale library
  • How to combine Modular Scale and Vertical Rhythm with Typi.

Sounds exciting, doesn’t it?

Before moving on, make sure you already know how to use the basic mixins and functions that Typi provides. Nothing is going to make sense without the foundations.

Let’s begin.

EM Media Queries with Typi

In the previous article, I showed you how to create multiple media queries with Typi just by using the $breakpoints and $typi maps. Although that’s neat, we have a problem. The media queries created by Typi are written in pixels. It’s a practice that web professionals frown upon :(

Instead of pixels, we should use the em unit for media queries. I’ve went deep down the rabbit hole and found that em media queries work the best across all browsers. You can read more about my tests in this article.

Moving on, there are two ways to make Typi create em media queries. The first way is to write your $breakpoints map with em units:

$breakpoints: (
  small: 25em, // 400px
  large: 50em // 800px
);

The CSS Typi creates is (Note the media queries):

html {
  font-size: 100%;
  line-height: 1.4;
}
@media all and (min-width: 25em) {
  html { font-size: 112.5%; }
}

@media all and (min-width: 50em) {
  html {font-size: 125%; }
}

We have em media queries now. The reason why this method works is because Typi outputs any value you provide to the $breakpoints map.

Although it works, the method isn’t elegant. You have to calculate the em values yourself. It’s a big headache for us developers who like to do as little work as possible.

There’s an alternative (much better way) to tell Typi to create em media queries. That is to use libraries that output media queries in em with Typi. Examples of these libraries include Mappy Breakpoint and Breakpoint.

Typi supports both libraries out of the box. Let me show you how to use them.

First of all, choose a library you’re comfortable with. Here are the installation instructions:

Mappy Breakpoints:

  • bower: bower install mappy-breakpoints --save
  • npm: npm install mappy-breakpoints --save

Breakpoint:

  • bower: bower install breakpoint-sass --save
  • npm: npm install breakpoint-sass --save

After installing the library, make sure you @import them before importing Typi:

// Choose either one. Make sure it comes before Typi
@import 'path-to-mappy-breakpoints/mappy-breakpoints';
@import 'path-to-breakpoints/stylesheets/breakpoint';

// Import Typi
@import 'path-to-typi/scss/typi';

The next step is to tell Typi to use either Mappy Breakpoint or Breakpoint by setting the $typi-breakpoint setting.

// If you use mappy-breakpoint
$typi-breakpoint: mappy-breakpoint;

// If you use breakpoint
$typi-breakpoint: breakpoint;

Once you’re done with these steps, go ahead and try compiling your Sass files. You see that pixel values within the $breakpoints map are converted into em values with both libraries.

html {
  font-size: 100%;
  line-height: 1.4;
}
@media all and (min-width: 25em) {
  html { font-size: 112.5%; }
}

@media all and (min-width: 50em) {
  html {font-size: 125%; }
}

Sweet, isn’t it? :)

I highly recommend this alternative method because you can take advantage of both Mappy Breakpoints and Breakpoint to create more complex queries.

Let’s run through an example.

Say you want to create a min-width and max-width query. Both Mappy Breakpoints and Breakpoint allow you to create such a query by writing two widths, like this:

// Mappy Breakpoint
@include mappy-bp(400px 800px) { //... }

// Breakpoint
@include breakpoint(400px 800px) { //... }

We can take this syntax and put it straight into the $breakpoints map:

$breakpoints: (
  small: 400px 800px
);

Then, both Mappy Breakpoints and Breakpoint will convert the small query into a query that contains (min-width: 400px) and (max-width: 800px).

The only difference is that Mappy Breakpoints subtracts 1px from the max-width query ((max-width: 799px)) to ensure that you don’t run into a case where some styles get overlapped at 800px.

/* Output from Mappy Breakpoints */
@media all and (min-width: 25em) and (max-width: 49.9375em) {
  html {font-size: 112.5%; }
}

/* Output from Breakpoint */
@media (min-width: 25em) and (max-width: 50em) {
  html {font-size: 112.5%; }
}

Neat eh? :)

The syntax for Mappy Breakpoint and Breakpoint differ, so if you want to create any other complex query, you’ll have to check out their respective documentations.

How about another example?

Let’s say you want to make a min-width and min-height query this time. This pattern is quite important when working with responsive typography.

In Mappy Breakpoints, you specify a height keyword, followed by the min-height you want:

$breakpoints: (
  small: 400px height 400px
);

In Breakpoint, you need to create a list with () and specify the query you want:

$breakpoints: (
  small: 400px (min-height 400px)
);

In both cases, you’ll get the same output:

@media all and (min-width: 25em) and (min-width: 25em) {
  html {font-size: 112.5%; }
}

I’m going to leave you here to experiment with other queries yourself. Be sure to check out the documentations (Mappy Breakpoints, Breakpoint) if you get stuck!

Let’s move on to the next tip.

Using Typi with Modular Scale

One best practice in web typography is to use modular scale to choose the font-size of your text elements.

When modular scale is concerned, it’s quite common to see people either use the modular scale calculator or manually calculate font-sizes by multiplying their bases with ratios over and over.

No matter which of the above methods you choose, you still have to input the values manually after getting the right sizes, like this:

h1 { font-size: 3.157em; }
h2 { font-size: 2.369em; }

If you choose to change your font-size at different media queries, then, this is what you’ll do:

h1 { font-size: 3.157em; }
h2 { font-size: 2.369em; }

@media all and (min-width: 25em) {
  h1 { font-size: 4.209em; }
  h2 { font-size: 3.157em; }
}

In Typi, we can create these CSS by using a font-map. (Yep, Typi font maps can take in em units as well):

$h1-map: (
  null: 3.157em,
  small: 4.209em
);

$h2-map: (
  null: 2.369em,
  small: 3.157em
);

h1 { @include typi($h1-map); }
h2 { @include typi($h2-map); }

There’s only one problem with this approach. It’s difficult to change the values of your modular scale.

What if you decided to change the ratio you used?

You have to calculate the sizes and change the values one by one… Boo :(

Luckily, there’s a way to make this much simpler. Scott Kellum and Tim Brown have made it easy for us by creating the Modular Scale Sass Library.

What you have to do is install the library either with bower, npm or download it manually:

  • bower: bower install modular-scale --save
  • npm: npm install modularscale-sass --save

Then, @import modular scale into your Scss file. This can come either before or after Typi.

@import 'path-to-modular-scale/stylesheets/modular-scale';

Once you’re done installing the library, you can use the ms() function to calculate font-sizes.

For example, you can write ms(3) if you wanted a value of 2.369em. It saves you a ton of effort either from calcuating or copy-pasting it.

$ms1: ms(1); // => 1em * 1.333 = 1.333em
$ms2: ms(2); // => 1em * 1.333 * 1.333 = 1.777em
$ms3: ms(3); // => 1em * 1.333 * 1.333 * 1.333 = 2.369em

The default ratio used in Modular Scale is 1.618. If you want to change this ratio, you can change the $ms-ratio setting:

$ms-ratio: 1.25;

$ms1: ms(1); // => 1em * 1.25 = 1.25em
$ms2: ms(2); // => 1em * 1.25 * 1.25 = 1.563em
$ms3: ms(3); // => 1em * 1.25 * 1.25 * 1.25 = 1.953em

The good news is, since Typi takes in a em based font-size, it integrates with ms() perfectly. You can write your font-maps like this:

$h1: (
  null: ms(4),
  small: ms(5)
);

With this change, you don’t have to worry about choosing the perfect scale your design tool before moving it into HTML. Everything can be calculated for you in Sass. So go ahead and play! Try out different scales and see which one fits your design best!

UPDATE: Because Modular Scale is so important, I made it even simpler to integrate modular scale (along with some other neat features) right into Typi. Read this article for more info.

Oh, we’ve come to the end of the second tip. How time flies. There’s one more tip for you in this article.

Combining Modular Scale with Vertical Rhythm with Typi

In the previous article, I showed you how to create line-height values both with the $typi map and your custom font map:

$typi: (
  null: (16px, 1.5) // Line height of 1.5
);

$h1-map: (
  null: (ms(3), 1.2) // Line height of 1.2
);

These line-height values (both 1.2 and 1.5) are called unitless line-height because no units (like px, em or rem) are attached to it.

Using unitless line-height is a recommended practice on the web because children elements can inherit the line-height value, then recompute their respectively line-height using their font-size instead of inheriting a computed value.

Although unitless line-heights are cool, it’s difficult to maintain Vertical Rhythm if we used them, especially if you chose your font-size with Modular Scale.

Let’s walk through an example to show what I mean.

Before we continue, I’m assuming you know what Vertical Rhythm is. If not, read this post.

Let’s say you have a font-size of 16px and a line-height of 24px. The font-size of your header text is 3.157em (50.5px).

When you use Vertical Rhythm on your sites, you want the line-height of your text elements to be a multiple of the baseline. So, the line-height of this header text is either going to be 48px, 60px or 72px (2, 2.5 or 3 baselines. See why you can use these multiples here)

The question is, what is 48px, 60px or 72px in unitless line-heights? There’s no way of calculating the value without doing some complex math.

For example, if you have a 60px line-height, your unitless line-height value should be 1.19 (60/50.5). You need to calculate the font-size value from modular scale, then calculate the unitless line height…

Which is a lot of work.

There’s a simpler way if you’re okay with not using unitless line-height for these elements.

If you remember, Typi has a vr() function that helps you calculate the number of baselines and output the value in rems. We know that 48px is two baselines, 60px is 2.5 baselines and 72px is three baselines.

So, if you want to simplify the calculation, you can use this vr() function directly within your font maps to calculate the line-height value.

$h1: (
  null: (ms(4), vr(2.5))
);

h1 {
  @include typi($h1);
}

The CSS produced by Typi is:

h1 {
  font-size: 3.157rem;
  line-height: 3.75rem; /* 2.5 baselines */
}

Tada! Beauty of using rems.

Many people, like Miriam Suzanne, the creator of Susy, have been using this approach for a long time.

By the way, I feel it’s okay to use rems in this case because it’s unlikely that you’re going to have text within <h1> that needs to inherit a raw line-height value. If you do, then, probably it’s time to take a look at your HTML.

Note: Don’t do this with the $typi map. You’ll want the line-height to remain unitless.

Wrapping Up

That’s it for now! You’ve learned how to:

  • Create Media Queries in em with Typi
  • Use Modular scale with Typi
  • Combine Modular Scale with Vertical Rhythm in Typi

There are other interesting things you can do with Typi. I’ll cover them in future blog posts :)

For now, play around with these newfound features! Let me know what you think of them in the comments below!

Thanks for reading. Did this article help you out? If it did, I hope you consider sharing it. You might help someone else out. Thanks so much!

Comments are closed

Please contact me if you want to talk to me about this article.

If you spot a typo, I’d appreciate if you can correct this page on Github. Thank you!

Hold on while i sign you up…

🤗
Woohoo! You’re in!
Now, hold on while I redirect you.