Photo by Olivier Giboulot on Unsplash
Self-hosting a font with Tailwind and SvelteKit
Updated for Tailwind v3
Table of contents
Note: This post can also be found on my main page at jvp.design/blog/self-hosting-a-font-with-ta..
A few months ago I wrote a post where I described how to self-host a font in SvelteKit. In that post I noted that it seemed that .ttf
font files weren't being properly recognized and that you would need to convert to .woff
files. Well, I don't know if I was just doing something wrong (most likely) or it was a function of Tailwind v3 being officially released or maybe an updated version of SvelteKit (both less likely), but there is an easier way to do this.
A quick thanks
First things first, I want to thank Dan for the comment on my other post, which caused me to come back and look at it again. The method in the previous post very well may have worked but it was going to be a pain in the butt to have to always go and convert the files when .tff
files are so much more widely available.
A note to site builders
If you're using SvelteKit the reason is likely because you care about performance. I wrote a bit about the benefits of custom sites over no-code or low-code builders on my other blog (jvp.design/blog/the-importance-of-a-web-pre..) but one thing I will mention is that if you're linking to Google Fonts in your site it will slow down the page load and will hurt performance. If getting that famed 💯 on the pagespeed/lighthouse performance metric is a goal then you need to self-host. That's not to say that if you don't self-host then the performance is going to be bad, but this is a very quick and easy way to squeeze just a bit more performance out of your site.
The process
I'm going to go in just a little more detail here than I did before. Here's what I'll do
- Set up a new SvelteKit app
- Install Tailwind v3
- Download a specific font
- Show how to use said font on your site
Setting up a new SvelteKit app
This is the easy part. You can follow along with two very simple descriptions; the one on SvelteKit's site or the one specific to SvelteKit on Tailwind's site. I'm going to stick with the former and then go over to Tailwind for part 2.
In case you don't want to go to another site (I know, why not just stay here???), you simply need to run npm init svelte my-app
and select "Skeleton project" and then choose whatever options you want. For the purposes of this project I'm not using any type checking nor am I including linting, prettier, or playwright.
Then you type
cd my-app
npm i
npm run dev -- --open
and you should have a running SvelteKit app that looks something like this
Installing Tailwind
As previously mentioned, we can go to Tailwind's site and skip to part 2 of the description. If you don't want to go there and just want to follow here, this is what you do.
Install dependencies
You'll need to install tailwind itself, as well as a couple of other dependencies.
npm i -D tailwindcss postcss autoprefixer svelte-preprocess
npx tailwindcss init tailwind.config.cjs -p
mv postcss.config.js postcss.config.cjs
Update svelte.config.js
Then you'll need to open the svelte.config.js
file and change it from this
import adapter from '@sveltejs/adapter-auto';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
}
};
export default config;
to this
import adapter from '@sveltejs/adapter-auto';
import { preprocess } from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [
preprocess({ postcss: true })
],
kit: {
adapter: adapter()
}
};
export default config;
Update tailwind.config.cjs
Then open tailwind.config.cjs
and add './src/**/*.{html,js,svelte,ts}'
to the content field. It should look like this
module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: []
};
Set up CSS file
Next you'll want to create a file called app.css
(or whatever you want to name it) and save it wherever you want. I tend to save it in ./src/styles/app.css
but you can save it anywhere. Then you'll want to add the "big 3" tailwind directives to this file.
// app.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Import app.css
into your layout
Finally, create a __layout.svelte
file in the ./src/routes
directory and import this newly-created css file.
<script>
import "../styles/app.css";
</script>
<slot />
remember where you saved your css file and replace what I've written as the file path with whatever you've chosen. Now your app should look like this
In order to make it a little more pleasing, let's open the ./src/routes/index.svelte
file and add a bit of styling. We'll wrap both elements in a div
so we can center the elements and add some basic text styling to both individual elements
<div class="h-screen grid place-content-center bg-gray-300">
<h1 class="text-5xl text-blue-600">Welcome to SvelteKit</h1>
<p class="text-xl text-red-500">Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
</div>
The app now looks like which is not great, but it's a little more visually appealing.
Using custom fonts
Download
I'm going to try this with two separate fonts: Walkway and Lobster Two. One is a .ttf
file format and the other is .otf
. I've created a new folder within the top-level static
folder called "fonts" and have saved both .zip
files there and subsequently extracted them there.
Now the file structure should look a bit like
Configure font-face
in CSS file
Now that we have the font files downloaded, we need to add the font face rules for the ones we want to use. Open up ./src/styles/app.css
and add the following:
@layer base {
@font-face {
font-family: 'Lobster Two';
src: local('Lobster Two'), local('Lobster-Two'), local('lobster two'), local('lobster-two'),
url('/fonts/lobster-two/LobsterTwo-Regular.otf');
font-weight: normal;
font-display: swap;
}
@font-face {
font-family: 'Lobster Two';
src: local('Lobster Two Bold'), local('Lobster-Two-Bold'), local('lobster two bold'),
local('lobster-two-bold'), url('/fonts/lobster-two/LobsterTwo-Bold.otf');
font-weight: bold;
font-display: swap;
}
@font-face {
font-family: 'Walkway';
src: local('Walkway'), local('walkway'), url('/fonts/Walkway/Walkway_Bold.ttf');
font-weight: normal;
font-display: swap;
}
@font-face {
font-family: 'Walkway';
src: local('Walkway'), local('walkway'), url('/fonts/Walkway/Walkway_Black.ttf');
font-weight: bold;
font-display: swap;
}
}
A few things to discuss:
@layer base
is the simplest way to incorporate these. For a bit more detail visit this site: tailwindcss.com/docs/adding-custom-styles#u..- I've added a bunch of possible spellings of the font names just in case the user already has them saved locally on their machine. I tend to like to replace spaces with hyphens and include title and lower case.
- I've added in
bold
andnormal
font weights, but you can add in whatever you need. For example, if you want to add a semi bold style toWalkway
you can directly set thefont-weight
property to be whichever numeric value would work (for semibold it's 600).Add font families to
Now that we've added them to the CSS, we need to indicate to Tailwind what we want to call them. For example, if you want to change the style of a specific line of text you can use the Tailwind classtailwind.config.cjs
font-<font-name>
where<font-name>
is whatever you're calling it. You'll see what I mean in a minute.
In tailwind.config.cjs
we're going to modify the extend
property like so:
theme: {
extend: {
fontFamily: {
walkway: ['Walkway'],
lobster: ['Lobster Two']
}
}
}
The values inside the array are the values that we set in the font-family
lines inside the CSS file. If, in app.css
we had replaced Lobster Two
with just Lobster
then we would also have to change that in tailwind.config.cjs
.
Style our app
Now that we've downloaded, installed, and declared our fonts the only thing left to do is to use them in the app itself. Open up ./src/routes/index.svelte
and use the fonts as you see fit. I've chosen to use font-walkway
on the h1
and font-lobster font-bold
on the p
tag. The code looks like this
<div class="h-screen grid place-content-center bg-gray-300">
<h1 class="text-5xl text-blue-600 font-walkway">Welcome to SvelteKit</h1>
<p class="text-xl text-red-500 font-lobster font-bold">Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
</div>
and the resulting app looks like this
Conclusion
There you have it, a very simple way to include not only .ttf
files but also .otf
files in your SvelteKit app. This may have seemed like a somewhat long process, but once you do it once or twice you get the hang of it and, like I said, it's a quick and easy way to add a small performance boost to the site you're working on, which is likely the reason you're using SvelteKit for your app instead of something like Next or Remix.