Rails 4: Why are fonts not loading in production?
Works with Rails >= 5 && sprockets >= 4:
src: url('Walkway_Bold-webfont.eot');
Works only in development because in development rails serves all app/assets
folder directly without pre-compilation (but not in production that's why rails can't find the fonts), so you can access what's inside app/assets
folder with just the url url
.
In production you need the pre-compiled version of these files. Rails precompile these files to public/assets
. To access these files, you need to
use sprockets helpers: font-url
or the more generic helper asset-url
.
src: font-url('Walkway_Bold-webfont.eot');
In addition, all folders under app/assets
will be pre-compiled automatically, you don't need to add fonts
folder to sprockets search path.
You can check search path with: Rails.application.config.assets.paths
in rails console.
Here is a generic way how to troubleshoot this problem for any library.
Reproduce error on local
Run rails server on production
- On terminal
rake assets:precompile
This on
config/environments/production.rb
# Rails 4 production # config.serve_static_files = true # Rails 5, Uncomment to run production on local # config.log_level = :debug config.public_file_server.enabled = true
- On terminal
RAILS_ENV=production rails s
- On terminal
- You should see error on web browser
Override font family
application.css
needs to be renamed toapplication.scss
sinceasset-url
will be usedAdd fonts to precompile on file
config/initializers/assets.rb
:Rails.application.config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
Look for font face definition inside your CSS library and copy that to
application.scss
. It should be something like:@font-face { font-family: 'my-library'; src: url('../fonts/my-library.eot'); src: url('../fonts/my-library.eot?#iefix') format('embedded-opentype'), url('../fonts/my-library.woff2') format('woff2'), url('../fonts/my-library.ttf') format('truetype'), url('../fonts/my-library.woff') format('woff'), url('../fonts/my-library.svg?#my-library') format('svg'); font-weight: normal; font-style: normal; }
Change to:
@font-face { font-family: 'my-library'; src: asset-url('my-library/fonts/my-library.eot'); src: asset-url('my-library/fonts/my-library.eot?#iefix') format('embedded-opentype'), asset-url('my-library/fonts/my-library.woff2') format('woff2'), asset-url('my-library/fonts/my-library.ttf') format('truetype'), asset-url('my-library/fonts/my-library.woff') format('woff'), asset-url('my-library/fonts/my-library.svg?#my-library') format('svg'); font-weight: normal; font-style: normal; }
What changes were made
- Use
asset-url
instead ofurl
- Change
../fonts
or similar to a path thatasset-url
understands.
What path to put on assets-url
To know which path asset-url
understands, go to rails console and enter Rails.application.assets.paths
. You will get something like:
[
'/path/1',
'/path/2',
'/path/3',
]
If your fonts are on /path/2/my-library/fonts/
then use
asset-url('my-library/fonts/my-library.eot')
.
i.e. You remove the path that part that you found on Rails.application.assets.paths
.
Check you wrote the right path
On Rails console on development:
helper.asset_url('my-library/fonts/my-library.eot')
Should return:
"/assets/my-library/fonts/my-library-2517b97e2c0e1e6c8ceb9dd007015f897926bc504154137281eec4c1a9f9bdc9.eot"
Note the trailing /assets/
and the digest in the last part.
We had this problem last week - the problem is that your assets will be compiled to have MD5 hashes on them, whilst your standard CSS will still be looking for their "standard" names. This is a problem with images & fonts.
@font-face {
font-family: 'akagi';
src: asset_url('fonts/akagi-th-webfont.eot');
src: asset_url('fonts/akagi-th-webfont.eot?#iefix') format('embedded-opentype'),
asset_url('fonts/akagi-th-webfont.woff') format('woff'),
asset_url('fonts/akagi-th-webfont.ttf') format('truetype'),
asset_url('fonts/akagi-th-webfont.svg#akagithin') format('svg');
font-weight: 300;
font-style: normal;
}
This is an example of how you should use scss files to load assets dynamically. These files are compiled (either before push or during init) into your .css files, all with their assets correctly synced.
We had a similar problem to you with Heroku, and managed to get it working by putting our files into /stylesheets/layout/fonts.css.scss and then calling
@import '/layout/fonts';
We also called our application.css -> application.css.scss to support the @import function