I'm trying to switch over from CRA to Vite to build my React projects, and I'm running into an issue where I can't get my fonts to load at all. The browser gives me the following error.
GET
http://localhost:5173/assets/fonts/Roboto-Regular.woff
[HTTP/1.1 404 Not Found 1ms]
downloadable font: download failed (font-family: "Roboto" style:normal weight:400 stretch:100 src index:0): status=2147746065 source: http://localhost:5173/assets/fonts/Roboto-Regular.woff
These are the font face rules I'm using.
// _fonts.scss
@font-face {
font-family: "Roboto";
src: url("../../assets/fonts/Roboto-Regular.woff") format("woff");
font-weight: 400;
}
And this is my index.scss file.
@use "./styles/partials/fonts" as *;
body {
font-family: "Roboto", Arial, Helvetica, sans-serif;
}
I thought it might be my folder structure, but that's not it either. I'm really confused as to why my fonts are loading when I do npm run dev and I've even tried to replicate the issue in a CRA project with no success at all.

I had the same issue (Vite + React) and leaving this here just in case it helps someone.
My CSS file was importing the font like this:
@font-face {
font-family: "Optimus Princeps";
src: url("./fonts/OptimusPrinceps.ttf") format("ttf") <- note the explicit format declaration
}
And it wouldn't work, visiting localhost:5173/src/fonts/OptimusPrinceps.ttf would download the file but the browser wouldn't display it.
What fixed it was removing the explicit declaration, blind guess. However, this could be because of how this specific font works and has nothing to do with Vite.
Working CSS:
@font-face {
font-family: "Optimus Princeps";
src: url("./fonts/OptimusPrinceps.ttf");
}
I found the issue. It has to do with how partial files work. If you aren't using a module bundler, sass expects you to write all links in your partial file as though you were writing a relative path to the scss file that would use that partial instead. So instead of writing:
src: url("../../assets/fonts/Roboto-Regular.woff") format("woff");
It should have been:
src: url("./assets/fonts/Roboto-Regular.woff") format("woff");
because that's the relative url that index.scss would use. You don't have to do this when using create-react-app so I mistakenly assumed Vite expected me to do something different entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With