Providing font options in a WordPress theme can be a significant design challenge.
It’s not quite as simple as just outputting a bit of inline CSS for font-family. Every font has unique meanlines and x-heights- so the font size, line heights and paddings for every font selector may need to be adjusted as well. A 1.2 line-height could be perfect in body text for “Helvetica Nueue”, but appear cramped with “Georgia”.

Unless you want to offer hundreds of options so that the user can also adjust these other css properties, it’s probably best to whittle down the font choices to a couple that look really great. I’d recommend adjusting the line heights and sizes automatically when the user makes a switch, which unfortunately, is a ton of extra work.
On a recent project I’ve been working on, I decided it wasn’t worth it. I kept the font face defaults and decided just give the user control over font colors and sizes. However, if you do want to offer your users that option, good on you.
What We’ll Cover
In this tutorial I won’t show how to adjust all the font properties- but I will suggest some ways to set up font options, and conditionally load Google fonts when a user has selected one.
In these examples I assume you’re using the Options Framework (theme or plugin version), but it should be fairly easy to use this code even if you’re building your own options panel from scratch.
Define the Font Arrays
I’d recommend selecting a limited number of fonts you think will look good with the theme. If you offer hundreds of fonts, your users will have to spend a long time finding which ones are the best. They might even select “Papyrus” or “Comic Sans“- and no one wants that.
When you have your font selections made, build out two arrays- one with the Google fonts, and another with system fonts. You should also supply fallback fonts in case the Google font doesn’t load or the user doen’t have the specific font on their system.
The reason I recommend building one array for system fonts and another for google fonts, is so we can easily check if the user select font is a Google font by comparing it against the Google array you’ve set.
In this example I also built a function that returns each of the font arrays. This is so I don’t have to redfine them in different functions or use a global variable.
Here’s how I set it up:
System Fonts
/**
* Returns an array of system fonts
* Feel free to edit this, update the font fallbacks, etc.
*/
function options_typography_get_os_fonts() {
// OS Font Defaults
$os_faces = array(
'Arial, sans-serif' => 'Arial',
'"Avant Garde", sans-serif' => 'Avant Garde',
'Cambria, Georgia, serif' => 'Cambria',
'Copse, sans-serif' => 'Copse',
'Garamond, "Hoefler Text", Times New Roman, Times, serif' => 'Garamond',
'Georgia, serif' => 'Georgia',
'"Helvetica Neue", Helvetica, sans-serif' => 'Helvetica Neue',
'Tahoma, Geneva, sans-serif' => 'Tahoma'
);
return $os_faces;
}
Google Fonts
/**
* Returns a select list of Google fonts
* Feel free to edit this, update the fallbacks, etc.
*/
function options_typography_get_google_fonts() {
// Google Font Defaults
$google_faces = array(
'Arvo, serif' => 'Arvo',
'Copse, sans-serif' => 'Copse',
'Droid Sans, sans-serif' => 'Droid Sans',
'Droid Serif, serif' => 'Droid Serif',
'Lobster, cursive' => 'Lobster',
'Nobile, sans-serif' => 'Nobile',
'Open Sans, sans-serif' => 'Open Sans',
'Oswald, sans-serif' => 'Oswald',
'Pacifico, cursive' => 'Pacifico',
'Rokkitt, serif' => 'Rokkit',
'PT Sans, sans-serif' => 'PT Sans',
'Quattrocento, serif' => 'Quattrocento',
'Raleway, cursive' => 'Raleway',
'Ubuntu, sans-serif' => 'Ubuntu',
'Yanone Kaffeesatz, sans-serif' => 'Yanone Kaffeesatz'
);
return $google_faces;
}
Setting Up the Options
Since I’m using the Options Framework, I’ll simply pass the font array to the ‘faces’ parameter in a typography option. If you’re setting up your own from scratch, it’s the same idea, you’ll just need to set up the select box html manually to output the fonts.
You’ll probably want to use a mix of Google and system fonts. To do this, you’ll need to combine the two arrays you defined in options_typography_get_google_fonts and options_typography_get_os_fonts, and then resort them into alphabetical order. Here’s how to do that:
$typography_mixed_fonts = array_merge( options_typography_get_os_fonts() , options_typography_get_google_fonts() ); asort($typography_mixed_fonts);
Now, set up the actual options.
In this example, you’ll notice the first option is only Google fonts, and the second two are a mix:
$options[] = array( 'name' => 'Selected Google Fonts', 'desc' => 'Fifteen of the top google fonts.', 'id' => 'google_font', 'std' => array( 'size' => '36px', 'face' => 'Rokkitt, serif', 'color' => '#00bc96'), 'type' => 'typography', 'options' => array( 'faces' => options_typography_get_google_fonts(), 'styles' => false ) ); $options[] = array( 'name' => 'System Fonts and Google Fonts Mixed', 'desc' => 'Google fonts mixed with system fonts.', 'id' => 'google_mixed', 'std' => array( 'size' => '32px', 'face' => 'Georgia, serif', 'color' => '#f15081'), 'type' => 'typography', 'options' => array( 'faces' => $typography_mixed_fonts, 'styles' => false ) ); $options[] = array( 'name' => 'System Fonts and Google Fonts Mixed (2)', 'desc' => 'Google fonts mixed with system fonts.', 'id' => 'google_mixed_2', 'std' => array( 'size' => '28px', 'face' => 'Arvo, serif', 'color' => '#ee9f23'), 'type' => 'typography', 'options' => array( 'faces' => $typography_mixed_fonts, 'styles' => false ) );
If you’ve done this correctly, you should now see something like this in the options panel:

Loading the Google Font
There are a couple ways to load Google fonts for a theme, but I think the stylesheet method is the easiest.
Since we have a couple typography options, with a mix of Google fonts and system fonts, we’ll need to check each of those options to see if a Google font has been selected. If it is a Google font, we’ll need to load the enqueue the font stylesheet from Google.
Here’s how I approached it:
/**
* Checks font options to see if a Google font is selected.
* If so, options_typography_enqueue_google_font is called to enqueue the font.
* Ensures that each Google font is only enqueued once.
*/
if ( !function_exists( 'options_typography_google_fonts' ) ) {
function options_typography_google_fonts() {
$all_google_fonts = array_keys( options_typography_get_google_fonts() );
// Define all the options that possibly have a unique Google font
$google_font = of_get_option('google_font', 'Rokkitt, serif');
$google_mixed = of_get_option('google_mixed', false);
$google_mixed_2 = of_get_option('google_mixed_2', 'Arvo, serif');
// Get the font face for each option and put it in an array
$selected_fonts = array(
$google_font['face'],
$google_mixed['face'],
$google_mixed_2['face'] );
// Remove any duplicates in the list
$selected_fonts = array_unique($selected_fonts);
// Check each of the unique fonts against the defined Google fonts
// If it is a Google font, go ahead and call the function to enqueue it
foreach ( $selected_fonts as $font ) {
if ( in_array( $font, $all_google_fonts ) ) {
options_typography_enqueue_google_font($font);
}
}
}
}
add_action( 'wp_enqueue_scripts', 'options_typography_google_fonts' );
/**
* Enqueues the Google $font that is passed
*/
function options_typography_enqueue_google_font($font) {
$font = explode(',', $font);
$font = $font[0];
// Certain Google fonts need slight tweaks in order to load properly
// Like our friend "Raleway"
if ( $font == 'Raleway' )
$font = 'Raleway:100';
$font = str_replace(" ", "+", $font);
wp_enqueue_style( "options_typography_$font", "http://fonts.googleapis.com/css?family=$font", false, null, 'all' );
}
In this example I manually defined each of the options and their defaults: google_font, google_mixed, google_mixed_2. If you have a dozen of these options that might get a bit tedious- I’m sure you could find a better way to do it.
Once the fonts are set in the $selected_fonts array, we get rid of any duplicates with array_unique.
Then loop through the remaining fonts and check if they are a google font (e.g. in_array( $font, $all_google_fonts )).
If font is in the Google font array, the options_typography_enqueue_google_font function is called to enqueue the font stylesheet.
You’ll notice that the “Raleway” font gets some special treatment. Although the majority of fonts in the Google library are loaded in the same format, a couple have special needs. You’ll want to test all the fonts you set up to make sure they work. You’ll also want to make sure that the appropriate italic and bold fonts are loaded if they’ll be required.
Setting the Font Style
There’s a number of ways to set the styles that have been selected in an options panel. I’ve found the easiest and most efficient is to generally load inline styles.
Here’s a quick example which outputs the inline styles for the first option:
/*
* Outputs the selected option panel styles inline into the <head>
*/
function options_typography_styles() {
$output = '';
$input = '';
if ( of_get_option( 'google_font' ) ) {
$input = of_get_option( 'google_font' );
$output .= options_typography_font_styles( of_get_option( 'google_font' ) , '.google-font');
}
if ( $output != '' ) {
$output = "\n<style>\n" . $output . "</style>\n";
echo $output;
}
}
add_action('wp_head', 'options_typography_styles');
In the Options Framework, typography options also have size, color and style associated with them. So, that same CSS can be outputted every time by re-using the options_typography_font_styles function:
/*
* Returns a typography option in a format that can be outputted as inline CSS
*/
function options_typography_font_styles($option, $selectors) {
$output = $selectors . ' {';
$output .= ' color:' . $option['color'] .'; ';
$output .= 'font-family:' . $option['face'] . '; ';
$output .= 'font-weight:' . $option['style'] . '; ';
$output .= 'font-size:' . $option['size'] . '; ';
$output .= '}';
$output .= "\n";
return $output;
}
Wrap Up
In my opinion, typography options are among the most difficult options to support. Has anyone else done it? Is your approach similar?
If you want to see working code, I’ve also included this demo in the Options Kit and the Options Theme Kit, which are paid demo packages for the Options Framework.