F
Filament12mo ago
John

Flash of unstyled text (FOUT) with self-hosted font

I'm facing a case of "Flash of unstyled text (FOUT)". I'm using a custom font, self-hosted:
// filament.css
@font-face {
font-family: 'Concert One';
font-style: normal;
font-weight: 400;
font-display: block; // previously 'swap'
src: url(../fonts/Concert_One/ConcertOne-Regular.ttf) format('truetype');
}
// filament.css
@font-face {
font-family: 'Concert One';
font-style: normal;
font-weight: 400;
font-display: block; // previously 'swap'
src: url(../fonts/Concert_One/ConcertOne-Regular.ttf) format('truetype');
}
The vite build will parse that url and make it available like so: http://localhost/build/assets/ConcertOne-Regular-56d2074a.ttf. The issue I'm facing is that the text flickers from browser default to my custom font. I've changed font-display from swap to block. It no longer flickers, but it takes about half a second to render. If I add this:
Filament::registerRenderHook(
'head.start',
fn() => Blade::render('<link rel="preload" href="http://localhost/build/assets/ConcertOne-Regular-56d2074a.ttf" as="font" type="font/ttf" crossorigin="anonymous">'),
);
Filament::registerRenderHook(
'head.start',
fn() => Blade::render('<link rel="preload" href="http://localhost/build/assets/ConcertOne-Regular-56d2074a.ttf" as="font" type="font/ttf" crossorigin="anonymous">'),
);
the problem is solved. But... that href is dynamically built by vite using a random hash. Is there another way to prevent this?
10 Replies
awcodes
awcodes12mo ago
Are you seeing this on production or only on dev. When you serve it with a built asset then hash won’t change every time, like it does in dev, so the browser would be able to cache it at point and this issue would become less likely to happen. Also hashes on fonts are always going to be more of a problem than a help. And aren’t needed in my opinion since the files themselves rarely change.
John
John12mo ago
Both. First with npm run dev, watching changes. Then with npm run build, where it generated the asset with hash as described above. Hmm, I thought the hash was random and would change every time I would deploy and npm build. But I see it stayed the same after another build, and will probably stay the same as long as the file contents don't change. (which won't happen) So I think the render hook is actually a viable solution.
awcodes
awcodes12mo ago
If the font file ever changes then the hash will change. But yea that will not be often. Personally I wouldn’t even let Vite touch the font stylesheet I would load it as a separate stylesheet and define a font family in the tailwind config to reference the name. And if your in the admin panel you can even just define the font’s stylesheet in the config and it will load it automatically.
John
John12mo ago
Yea, I looked at the config option, but it will load some google scripts. The whole reason I'm serving local font files is because I don't want 3rd party calls because of GDPR. I'll look into serving them outside Vite, which makes more sense. Thanks!
awcodes
awcodes12mo ago
The config is just a url right. So you could load any stylesheet. You could also use https://fonts.bunny.net/. It’s gdpr replacement for google fonts.
Bunny Fonts | Explore Faster & GDPR friendly Fonts
Bunny Fonts help make the internet faster, safer and GDPR compliant!
John
John12mo ago
It will still leave your IP at google because of the preconnect:
@if (filled($fontsUrl = config('filament.google_fonts')))
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="{{ $fontsUrl }}" rel="stylesheet" />
@endif
@if (filled($fontsUrl = config('filament.google_fonts')))
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="{{ $fontsUrl }}" rel="stylesheet" />
@endif
But... Bunny Fonts seems like an easier fix altogether. I didn't know about it. I keep learning every day... Thanks again!
awcodes
awcodes12mo ago
Ah, you’re right. You’ll be able to do it in v3 Panels. 🙂
John
John12mo ago
Can't wait for v3. You think it's hard to upgrade from v2?
awcodes
awcodes12mo ago
Not really. Some plugin updates might be complicated. V3 will have an upgrade script that will handle like 90% of the process for you.
John
John12mo ago
😮 That's great to hear!