Select Page

Add Custom Fonts to a WordPress Site Without Any Plugins

Let’s dive into how to add custom fonts to WordPress without using any plugins.

Choose a Font

Originally, I was using a font called “Arrow” from DaFont. This actually ended up giving me problems later on, something I’ll cover later.

Convert to WOFF2 (if you need to)

Any font in the entire world. Just make sure it’s in a format that’s good for the web, like woff2. If your font isn’t already in woff2 format, there’s a really nifty command line tool to convert (compress, actually) your font into the preferred format before we get going.

sudo apt update

sudo apt install woff2


woff2_compress [path-to-font-file]

This command will automatically compress the file to .woff2 and name it the same as your input filename and place it in the same directory.

Upload Font to Child Theme

I just put it in the root directory of my child theme, under /fonts

├── fonts
│   └── Almo_Andrea_FontlabARROW.woff2
├── functions.php
├── screenshot.png
├── style.css
└── theme.json

Enqueue Font

Enqueue your font inside functions.php like so:

function my_plugin_add_stylesheet() {
    wp_register_style( 'arrowFont', get_stylesheet_directory_uri() . '/fonts/Almo_Andrea_FontlabARROW.woff2');
    wp_enqueue_style( 'arrowFont' );
add_action( 'wp_enqueue_scripts', 'my_plugin_add_stylesheet' );

Typically, in the past, you’d have to call a @font-face rule in your CSS in order to assign that font to various elements. Additionally, if you’re using a child theme to handle your fonts, in the past, you’d have to make rules for how to implement your custom fonts in addition to your @font-face rule. However, as of WordPress 5.9, the @font-face rule is actually handled via theme.json.

Add Font To Any/All Blocks via theme.json

In my case, I’m riffing off of the TwentyTwentyTwo theme, so in my child theme, I just copied over the theme.json file to make my modifications. In my case, I’m looking for where the default font is registered. I found it around like 170, but it’s gonna look something like this:

"typography": {
			"dropCap": false,
			"fontFamilies": [
					"fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
					"name": "System Font",
					"slug": "system-font"
					"fontFamily": "\"Source Serif Pro\", serif",
					"name": "Source Serif Pro",
					"slug": "source-serif-pro",
					"fontFace": [
							"fontFamily": "Source Serif Pro",
							"fontWeight": "200 900",
							"fontStyle": "normal",
							"fontStretch": "normal",
							"src": [ "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2" ]
							"fontFamily": "Source Serif Pro",
							"fontWeight": "200 900",
							"fontStyle": "italic",
							"fontStretch": "normal",
							"src": [ "file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Italic.ttf.woff2" ]

In this section, you’ll want to update everything that needs to change to match what you’ve got going on in your child theme and whatever font you’ve chosen. In my case, I’ve updated “fontFamily”, “name”, “slug”, “src” and the “font-face” to match my font and child theme file paths.

Once you’ve updated everything under “typeography”, now you can move on and update the “name” value for each of the blocks you want to use the new font on. By default the headers get their own font and it’s specified by the css variable var(--wp--preset--font-family--source-serif-pro). I changed the last bit with the slug that I set for my font, so my slug was arrow. My modifications looked like so:

	"styles": {
		"blocks": {
			"core/button": {
				"border": {
					"radius": "0"
				"color": {
					"background": "var(--wp--preset--color--primary)",
					"text": "var(--wp--preset--color--background)"
				"typography": {
					"fontSize": "var(--wp--preset--font-size--medium)"
			"core/post-title": {
				"typography": {
					"fontFamily": "var(--wp--preset--font-family--arrow)",
					"fontWeight": "300",
					"lineHeight": "var(--wp--custom--typography--line-height--tiny)",
					"fontSize": "var(--wp--custom--typography--font-size--gigantic)"

Just keep updated the last part of that variable until you’ve changed all the blocks you’re trying to target with your new font. That’s it! Hope this helped someone.

Potential Issues: Font Weight

Something I’d like to note when you add custom fonts to WordPress… When you define your font inside of your theme.json, you’re required two things in order to register a font. From my understanding, these two requirements to register a font are actually coming from the CSS rule @font-face which requires a font family and a font weight attribute.

If you were like me, and using a custom font that didn’t specify different weights within the font file itself, this can potentially be an issue. If @font-face can’t detect a font weight within the file inside of your src, then it won’t load the font and will use some default system fallback.

To fix and/or avoid this issue, be sure to use a font that defines at least one font weight, and be sure to match that particular font weight within your @font-face call inside theme.json

Check out more articles

How to Generate a Ranger Config File

ranger --copy-config=all This will copy all the default config files from /usr/local/lib so you can make edits without messing anything up. Huge shout out to for explaining this and so much more. Took me a...

First Open Source Contribution

Surprise! I genuinely did not plan on making my first ever open source contribution today. In fact, I didn't plan on a lot of things happening this week at all. I recently got an awesome opportunity to work on a site that is being hosted on a platform called Pantheon,...

How to Exclude Specific Posts and Pages from WP_QUERY

For the sake of having something to work with, let's suppose we've got the following query:In this query, inside the $args array, there's a special parameter that allows you to exclude specific posts and pages from the query. This parameter is called post__not_in and...

Configure SSH For Password-less Connections

Preamble I'm slightly embarrassed to admit this, but it was a long time before I figured out how amazing this little file is and how exactly to put it to good use. The file I'm talking about is the SSH config file. By default, when you first connect to a server via...

WordPress Site Stuck in Maintenance Mode

Plugin Error Code 500 During Update While I was updating a WordPress plugin locally, something happened on my local server to trigger a 500 error code as the plugin was updating. On the frontend, I refreshed the page and was greeted with "Briefly Unavailable for...

Creating a WordPress Plugin Downloader

How it Started I was recently tasked with the challenge of creating a WordPress theme generator. The idea being, instead of writing your style.css file from scratch, you'd be able to just answer a few simple questions about how you'd like your theme set up, and those...

Fix Audio on XFCE Chromebook

The Problem After moving from GalliumOS to Xubuntu, I noticed that playing YouTube videos on both Firefox and Chromium would result in decent playback for a few minutes, but suddenly the audio would turn into a solid beeping tone while the YouTube video displayed the...

Adjust Trackpad Sensitivity XFCE

xinput set-prop "Elan Touchpad" "Synaptics Finger" 1 1 1 What are the values 1 1 1? This sets the sensitivity as close to the original ChromeOS as possible. Larger numbers will decrease sensitivity of various aspects. I never looked into which individual value...

Fireworks (Short Film) About the film Year: 2020 Director/DP: Tim Searfoss Writers: Matt Jones, Tim Searfoss Sound Mix: Matt Jones

Hosting Multiple Sites Using LocalWP

I've done a write-up on hosting local WordPress sites before, but I definitely prefer this method over the previous one. If you've never tried hosting multiple sites using LocalWP, then I'd encourage you to check it out. I've had really bad issues with it in the past,...