Serving fonts with Propshaft and Tailwind

13 Apr 23

Recently I've been using tailwindcss more and more to style web applications, with propshaft as my preferred asset pipeline since Rails 7. Often, custom fonts are needed when designing and building web applications. This post will focus on how to use both tools in a Rails application to serve custom fonts.

#Custom fonts with Tailwind

You can configure a custom font using a service like Google Fonts by adding links to the head of your layout and defining the font in your Tailwind config.

<!-- app/views/layouts/application.html.erb -->

<head>
  <!-- ... -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
  <!-- ... -->
</head>
// config/tailwind.config.js

module.exports = {
  // ...
  theme: {
    extend: {
      // ...
      fontFamily: {
        poppins: ['Poppins', 'sans-serif'],
      },
    },
  }
}

The custom font can then be applied using the font-poppins class.

This approach works well, is easy to configure, and is likely to be served to the client from a Content Delivery Network (CDN) —which can mean fast, cached responses.

However, there are times when you might need to serve fonts directly from your application.

#Serving custom fonts with Propshaft

Propshaft is a new asset pipeline for Rails 7, designed to be a simpler and faster solution compared to previous options (e.g. Sprockets).

By default, Propshaft will make all assets in directories in app/assets available to be served and will copy them all to public/assets when precompiling.

This means you can add a downloaded font to app/assets/fonts and it will "just work".

In this example, I've downloaded the Chivo Mono font and saved it as app/assets/fonts/chivo-mono.ttf.

Then we can configure Tailwind to use the font. We need to define the font in the config, and define a font-face rule in our CSS.

// config/tailwind.config.js

module.exports = {
  // ...
  theme: {
    extend: {
      // ...
      fontFamily: {
        chivo: ['Chivo Mono', 'sans-serif'],
      },
    },
  }
}
/* app/assets/stylesheets/application.tailwind.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  @font-face {
    font-family: 'Chivo Mono';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('chivo-mono.ttf');
  }
}

Again, the font-chivo class can be used to apply the font to elements in your HTML.

It's important to note that Propshaft copies all assets to public/assets in a flat structure, irrespective of the directory it is placed in app/assets.

This means we only need to reference chivo-mono.ttf, rather than fonts/chivo-mono.ttf.

This gotcha might seem obvious, but it tripped me up for long enough to write this post!