Over the past year I've had the pleasure of developing a full-stack application using the Remix framework and it was a bit tricky to get rid of the css jank when rendering Fontawesome icons.
When using Fontawesome via React, it dynamically injects css into pages that require icons. This is fine for client rendered applicatioins but for server-side rendered markup, the icon exists before the CSS is loaded leading to a visible icon resize (or in some cases, no resize leading to a weird-looking / broken layout).
The solution here is to use Fontawesome's dom
object and add its css directly to the head
tag. However with Remix, it is a bit tricky to inject arbitary css into the head
component. What is
supported however is adding css via a link/href
. So the workaround is to create a resource route that
emits Fontawesome's css:
// api.font-awesome-css.tsx import { dom } from "@fortawesome/fontawesome-svg-core"; import { LoaderArgs } from "@remix-run/node"; export async function loader({ params }: LoaderArgs) { return stylesheet(dom.css()); } function stylesheet(content: string, init: ResponseInit = {}) { let responseInit = typeof init === "number" ? { status: init } : init; let headers = new Headers(responseInit.headers); if (!headers.has("Content-Type")) { headers.set("Content-Type", "text/css; charset=utf-8"); } return new Response(content, { ...responseInit, headers, }); }
We can then subequently modify root.tsx
to include this css and disable Fontawesome's automatic css
injection (since we are doing it manually):
// root.tsx import { config as fontAwesomeConfig } from "@fortawesome/fontawesome-svg-core"; fontAwesomeConfig.autoAddCss = false; export const links: LinksFunction = () => [ ...(cssBundleHref ? [ { rel: "stylesheet", href: globalStylesUrl, }, { rel: "stylesheet", href: cssBundleHref }, { rel: "stylesheet", href: "/api/font-awesome-css" }, ] : [ { rel: "stylesheet", href: globalStylesUrl, }, { rel: "stylesheet", href: "/api/font-awesome-css" }, ]), ];
Many thanks to Spencer for the original solution for Next.js.