# Self-hosting a font with Tailwind and SvelteKit

**Note:** This post can also be found on my main page at https://www.jvp.design/blog/self-hosting-a-font-with-tailwind-and-sveltekit

A few months ago I wrote a [post](https://jeffpohlmeyer.com/self-hosting-a-font-with-tailwind-jit-and-sveltekit) 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](https://tailwindcss.com/) 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](@danxcraig) 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 (https://www.jvp.design/blog/the-importance-of-a-web-presence-in-2022) 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](https://kit.svelte.dev/) or the one specific to SvelteKit on [Tailwind's site](https://tailwindcss.com/docs/guides/sveltekit). 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.
![Screen Shot 2022-05-24 at 10.13.30 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1653401619923/zi_wwIA02.png align="left")
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
![Screen Shot 2022-05-24 at 10.14.56 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1653401711475/o6sx6brWj.png align="left")

## Installing Tailwind
As previously mentioned, we can go to [Tailwind's site](https://tailwindcss.com/docs/guides/sveltekit) 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
![Screen Shot 2022-05-24 at 10.27.19 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1653402455187/4uqPz3xDO.png align="left")
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
![Screen Shot 2022-05-24 at 10.42.38 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1653403378366/3mc7EExit.png align="left")
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](https://www.fontsquirrel.com/fonts/Walkway) and [Lobster Two](https://www.fontsquirrel.com/fonts/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
![Screen Shot 2022-05-24 at 11.00.30 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1653405405251/MaSGGnHFW.png align="left")
### 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: https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
- 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` and `normal` font weights, but you can add in whatever you need. For example, if you want to add a semi bold style to `Walkway` you can directly set the `font-weight` property to be whichever numeric value would work (for semibold it's 600).
### Add font families to `tailwind.config.cjs`
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 class `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
![Screen Shot 2022-05-24 at 11.29.53 AM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1653406223419/Cwb9gW1bC.png align="left")
## 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.
