Serving custom fonts with cssbundling-rails

Mikael Henriksson
2 min read

Choosing a font 


My font of choice is Open Sans; I downloaded it and added the various font files to the `app/assets/fonts/OpenSans` directory. 


Using .css.erb 


First, to make the `asset_url` helpers work, we need to use a `.css.erb` file to direct the fonts through the asset pipeline. Using paths directly won't be possible in production when the assets have had a digest added to them.
 

// ./app/assets/stylesheets/opensans.css.erb

@font-face {
  font-family: "Open Sans";
  src: url("<%= font_path('OpenSans/Bold/OpenSans-Bold.woff2') %>") format("woff2"),
       url("<%= font_path('OpenSans/Bold/OpenSans-Bold.woff') %>") format("woff"),
       url("<%= font_path('OpenSans/Bold/OpenSans-Bold.ttf') %>") format("truetype");
  font-weight: bold;
  font-style: normal;
}
@font-face {
  font-family: "Open Sans";
  src: url("<%= font_path('OpenSans/BoldItalic/OpenSans-BoldItalic.woff2') %>") format("woff2"),
       url("<%= font_path('OpenSans/BoldItalic/OpenSans-BoldItalic.woff') %>") format("woff"),
       url("<%= font_path('OpenSans/BoldItalic/OpenSans-BoldItalic.ttf') %>") format("truetype");
  font-weight: bold;
  font-style: italic;
}
@font-face {
  font-family: "Open Sans";
  src: url("<%= font_path('OpenSans/ExtraBold/OpenSans-ExtraBold.woff2') %>") format("woff2"),
       url("<%= font_path('OpenSans/ExtraBold/OpenSans-ExtraBold.woff') %>") format("woff"),
       url("<%= font_path('OpenSans/ExtraBold/OpenSans-ExtraBold.ttf') %>") format("truetype");
  font-weight: 800;
  font-style: normal;
}
@font-face {
  font-family: "Open Sans";
  src: url("<%= font_path('OpenSans/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff2') %>") format("woff2"),
       url("<%= font_path('OpenSans/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff') %>") format("woff"),
       url("<%= font_path('OpenSans/ExtraBoldItalic/OpenSans-ExtraBoldItalic.ttf') %>") format("truetype");
  font-weight: 800;
  font-style: italic;
}

Newer rails versions have fixed this problem in the following PR. Since December 2021 it should be possible to make it work with the following adjustments:
 

// ./app/assets/stylesheets/opensans.css

@font-face {
  font-family: "Open Sans";
  src: url("OpenSans/Bold/OpenSans-Bold.woff2") format("woff2"),
       url("OpenSans/Bold/OpenSans-Bold.woff") format("woff"),
       url("OpenSans/Bold/OpenSans-Bold.ttf") format("truetype");
  font-weight: bold;
  font-style: normal;
}
@font-face {
  font-family: "Open Sans";
  src: url("OpenSans/BoldItalic/OpenSans-BoldItalic.woff2") format("woff2"),
       url("OpenSans/BoldItalic/OpenSans-BoldItalic.woff") format("woff"),
       url("OpenSans/BoldItalic/OpenSans-BoldItalic.ttf") format("truetype");
  font-weight: bold;
  font-style: italic;
}
@font-face {
  font-family: "Open Sans";
  src: url("OpenSans/ExtraBold/OpenSans-ExtraBold.woff2") format("woff2"),
       url("OpenSans/ExtraBold/OpenSans-ExtraBold.woff") format("woff"),
       url("OpenSans/ExtraBold/OpenSans-ExtraBold.ttf") format("truetype");
  font-weight: 800;
  font-style: normal;
}
@font-face {
  font-family: "Open Sans";
  src: url("OpenSans/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff2") format("woff2"),
       url("OpenSans/ExtraBoldItalic/OpenSans-ExtraBoldItalic.woff") format("woff"),
       url("OpenSans/ExtraBoldItalic/OpenSans-ExtraBoldItalic.ttf") format("truetype");
  font-weight: 800;
  font-style: italic;
}


Adding opensans.css to manifest.js 


Then we have to add the particular font file to the asset manifest. This step ensures that the assets are served both in development and production.
 

// ./app/assets/config/manifest.js

//= link_tree ../fonts
//= link_tree ../images
//= link_tree ../builds
//= link opensans.css
//= link_tree ../../javascript .js



Configure TailwindCSS 


To use our custom font as default in TailwindCSS, we need to add `Open Sans` to them sans fonts.
 

// ./tailwind.config.js

module.exports = {
  content: [
    "./app/**/*.html.erb",
    "./app/helpers/**/*.rb",
    "./app/javascript/**/*.js",
    "./app/assets/stylesheets/**/*.js",
    "./app/components/**/*.js",
    "./app/components/**/*.css"
  ],
  theme: {
    fontFamily: {
      sans: [
        "Open Sans",
        "ui-sans-serif",
        "system-ui",
        "-apple-system",
        "BlinkMacSystemFont",
        '"Segoe UI"',
        "Roboto",
        '"Helvetica Neue"',
        "Arial",
        '"Noto Sans"',
        "sans-serif",
        '"Apple Color Emoji"',
        '"Segoe UI Emoji"',
        '"Segoe UI Symbol"',
        '"Noto Color Emoji"'
      ]
    }
  }
}



Precompiling opensans.css.erb 


Precompile the erb asset to make use of it in the assets pipeline:
 

# ./app/config/initializers/assets.rb

Rails.application.config.assets.precompile += %w[opensans.css.erb]



Loading opensans 


The last step is to load the font file in the application.html.erb.
 

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

<!DOCTYPE html>
<html class="min-h-screen">
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag "opensans", "data-turbo-track": "reload", defer: true %>
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload", defer: true %>
    <%= javascript_importmap_tags %>
  </head>
</html>



Comments