Use Font Awesome icons in Phoenix with Tailwind 4
If you are using Tailwind 3, please see this post
It’s great that Phoenix comes with Heroicons support out the box, but I use Font Awesome and wanted to use those in the same way. This post will show you how you can swap out Heroicons and make a few changes so that the .icon
component works with Font Awesome instead.
There are a few ways to use Font Awesome icons but this post will show you how to use the SVG icons hosted within your project in the same way that Heroicons work.
Step 1. Download the SVG files
Go to the Font Awesome download page and download the “version for the web” you’re going to use.
For this example, I’ll download the Free for Web version.
Step 2. Save the icons to your assets/vendor directory
-
Delete the directory
assets/vendor/heroicons
-
Unzip the Font Awesome download and copy the contents of
svgs/
intoassets/vendor/fontawesome
so you have:assets/vendor/fontawesome/brands assets/vendor/fontawesome/regular assets/vendor/fontawesome/solid
If you’re using the pro version, then copy in the SVG directories you want to use.
Step 3: Create a fontawesome.js plugin
Copy vendor/heroicons.js
to vendor/fontawesome.js
and make the following changes:
-
Change the path to the icons
"../../deps/heroicons/optimized"
to"fontawesome/svgs"
-
Change the icon variants to match the Font Awesome icons. In this case we’re using regular as default, and changing
-mini
to-brand
. You can add other Fonteawesome variants here as well, like-light
. -
Change all occurrences of
hero
tofa
The icon naming will change from hero-<name>
to fa-<name>
, hero-<name>-mini
to fa-<name>-brand
, and hero-<name>-solid
to fa-<name>-solid
.
@@ -1,16 +1,15 @@
-// A Tailwind plugin that makes "hero-#{ICON}" classes available
+// A Tailwind plugin that makes "fa-#{ICON}" classes available
const plugin = require("tailwindcss/plugin")
const fs = require("fs")
const path = require("path")
module.exports = plugin(function({matchComponents, theme}) {
- let iconsDir = path.join(__dirname, "../../deps/heroicons/optimized")
+ let iconsDir = path.join(__dirname, "fontawesome/svgs")
let values = {}
let icons = [
- ["", "/24/outline"],
- ["-solid", "/24/solid"],
- ["-mini", "/20/solid"],
- ["-micro", "/16/solid"]
+ ["", "/regular"],
+ ["-solid", "/solid"],
+ ["-brand", "/brands"],
]
icons.forEach(([suffix, dir]) => {
fs.readdirSync(path.join(iconsDir, dir)).forEach(file => {
@@ -19,7 +18,7 @@ module.exports = plugin(function({matchComponents, theme}) {
})
})
matchComponents({
- "hero": ({name, fullPath}) => {
+ "fa": ({name, fullPath}) => {
let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "")
content = encodeURIComponent(content)
let size = theme("spacing.6")
@@ -29,9 +28,9 @@ module.exports = plugin(function({matchComponents, theme}) {
size = theme("spacing.4")
}
return {
- [`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
- "-webkit-mask": `var(--hero-${name})`,
- "mask": `var(--hero-${name})`,
+ [`--fa-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
+ "-webkit-mask": `var(--fa-${name})`,
+ "mask": `var(--fa-${name})`,
"mask-repeat": "no-repeat",
"background-color": "currentColor",
"vertical-align": "middle",
Step 4: Change the reference from heroicons to fontawesome in main.css
@@ -6,7 +6,7 @@
@source "../js";
@source "../../lib/trelany/web";
-@plugin "../vendor/heroicons";
+@plugin "../vendor/fontawesome";
/* daisyUI Tailwind Plugin. You can update this file by fetching the latest version with:
cd assets/vendor && curl -sLO https://github.com/saadeghi/daisyui/releases/latest/download/daisyui.js && cd ../../
Make sure to look at the daisyUI changelog: https://daisyui.com/docs/changelog/ */
Step 5: Modify your components file.
Do a search and replace across your core_components.ex file changing "hero-" to "fa-". The most important change is the icon/1
function which needs to match on "fa-"
. Note, not all the icons have a direct replacement so you may still need to find those icons and give them names that match the Font Awesome library.
@@ -417,13 +417,13 @@ defmodule MyAppWeb.CoreComponents do
## Examples
- <.icon name="hero-x-mark-solid" />
- <.icon name="hero-arrow-path" class="w-3 h-3 ml-1 motion-safe:animate-spin" />
+ <.icon name="fa-x-mark-solid" />
+ <.icon name="fa-arrow-path" class="w-3 h-3 ml-1 motion-safe:animate-spin" />
"""
attr :name, :string, required: true
attr :class, :string, default: nil
- def icon(%{name: "hero-" <> _} = assigns) do
+ def icon(%{name: "fa-" <> _} = assigns) do
~H"""
<span class={[@name, @class]} />
"""
Step 6: Cleanup
Remove :heroicons
from your mix.exs
file.
Step 7: Use Font Awesome
You can now use any Font Awesome icons in your code with <.icon name="fa-rocket-solid" />
I hope that helps.