Loading custom fonts in Phoenix is straight-forward, but it's still easy to slightly misunderstand how asset directories work and end up with an error like the following:
ERROR in ./css/app.css
Module build failed: ModuleNotFoundError: Module not found: Error: Can't resolve './fonts/awesome-webfont.woff' in '/Users/alchemist/reactor/assets/css'
at /Users/alchemist/reactor/assets/node_modules/webpack/lib/Compilation.js:518:10
Where to put the font files
Font files such as a .ttf, .otf or .woff (recommended) go in the assets/static/fonts
directory. You may not have the directory created but it will be copied to priv/static/fonts
, which can serve static assets by default. That's because the endpoint.ex
file created when you generate a new project contains:
plug Plug.Static,
at: "/",
from: :your_app,
gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt)
How to configure Webpack for font files
First you'll need to install file-loader in your assets directory with yarn:
yarn --cwd=assets add file-loader -D
or with npm:
npm --prefix=assets install file-loader --save-dev
Then, inside the webpack.config.js
file in your assets directory, add the following rule to the array of rules inside the module object in the module.exports
:
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: { name: '[name].[ext]', outputPath: '../fonts' }
},
],
}
After this step, you can verify Webpack is processing your file by checking to see if it's copied into the priv/static/fonts
when you run your app in development via mix phx.server
.
Declare the @font-face in your CSS
At the top of your app.css
file, use the @font-face
directive to declare your font and then create a CSS rule that uses it:
@font-face {
font-family: 'amazing_regular';
src: local('amazing_regular'), url('../static/fonts/amazing-webfont.woff') format('woff');
font-weight: normal;
font-style: normal
}
h1 {
font-family: "amazing_regular";
}
Note that the src:
portion of the font declaration includes two addresses. The the local source is for users who already have the font on their system and the url is for those who don't.
Done!