Loading Google Fonts from Theme Options

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.

About Devin

I am a developer based in Austin, Texas. I run a little theme shop called DevPress and help manage a WooCommerce shop with Universal Yums. Find me on twitter @devinsays.

66 Responses

  1. Is indeed awesome, and I’d like to +1 using a selection of the best Google fonts. The overhead of including more than a handful of the best probably isn’t worth it when you look at the quality of the fonts available (although I’ll probably add Lato to my list which I’ve found quite useful).

    Rockitt seemed to have disappeared a while ago though?

  2. As we know some of Google fonts have different font-weight (100, 200 and so on) but other don’t have.
    Do you have any idea how to set font-weight depend on particular font?

    1. I added this code in the options-sanitize.php file (line 342) and it works for me. Now i can add 100, 200, 300, etc value for the css font-weight.

      function of_recognized_font_styles() {
      $default = array(
      ‘normal’ => __( ‘Normal’, ‘options_framework_theme’ ),
      ‘italic’ => __( ‘Italic’, ‘options_framework_theme’ ),
      ‘bold’ => __( ‘Bold’, ‘options_framework_theme’ ),
      ‘bold italic’ => __( ‘Bold Italic’, ‘options_framework_theme’ ),
      ‘100’ => __( ‘100’, ‘options_framework_theme’ ),
      ‘200’ => __( ‘200’, ‘options_framework_theme’ ),
      ‘300’ => __( ‘300’, ‘options_framework_theme’ ),
      ‘400’ => __( ‘400’, ‘options_framework_theme’ ),
      ‘500’ => __( ‘500’, ‘options_framework_theme’ ),
      ‘600’ => __( ‘600’, ‘options_framework_theme’ ),
      ‘700’ => __( ‘700’, ‘options_framework_theme’ ),
      ‘800’ => __( ‘800’, ‘options_framework_theme’ ),
      ‘900’ => __( ‘900’, ‘options_framework_theme’ ),
      );
      return apply_filters( ‘of_recognized_font_styles’, $default );
      }

      1. david

        Hey Im trying to add the 100,200 etc as well. I dont see an options-sanitize.php file. Any suggestions where I can enter that code or where that similar code is? Thanks

  3. Hi Devin,

    I’ve been using your options framework for a few weeks now and it is absolutely amazing.

    I also want to support Google Webfonts, but I have no idea, where to put the code snippet, that actually loads the font from Google’s API. Could you tell me, where to place the code?

    Thanks
    Lukas

  4. Sara

    Pardon me if I didn’t really get this, but does your framework include an option to add like ALL Google fonts in it and thus give the client the ability to choose any font they want from the options panel?
    I mean I’m a beginner theme developer and I see many WP themes saying they have “hundreds of Google web fonts” included, I’m sure they don’t include them manually one by one, so is there a way to load all the Google fonts into your framework? It would be great to have everything included in one framework.
    I just wanted to say that I just followed u on twitter, and that this framework is a genius thing and I can’t believe I ran into your site and learned about it.
    Thank you :)

      1. Sara

        I understand. Thank you for your reply, Devin. I’m looking forward to buying and using your framework in my next WordPress theme project. Thank you for replying, again, and for such a great job on this framework.
        Sara.

      1. Jonah Brown

        What would be the best way to make a function that can add a google font to this. that way I have a default list but then hook in a font my client may want.

        thanks

  5. Mel

    Hi Devin,

    The option framework is awesome.

    anyway i am having an issue with this functions for fonts.

    the google fonts drop down was good it has an output inside the THEME OPTIONS in admin area but the two other drop down (the mixed fonts) it has no output.

    I checked all the codes and are all the same I actually copy paste the codes..

    Please help.

    Thanks
    Mel

  6. Bilal Erdinc

    Hi Devin,
    what about a demo of the selected font? It is built in or have we do some modification?
    Amazing framework by the way!

  7. Dean

    Hi Devin

    I am having some trouble getting the Google Fonts Tutorial to work. I am probably missing something completely obvious here.

    I can successfully output the stylesheet in the head of my template, but how do you go about getting the font options to change the css selectors in the stylesheet?

    Thanks

      1. Dean

        Ok – so should this be included in the functions.php ? i’m having no luck with getting it to output the inline styles.

  8. First i am really thanksful for it i used this code in my theme and its working great but on my client website (server) its showing error .

    Warning: Illegal string offset ‘face’ in /homepages/45/d459633490/htdocs/wp-content/themes/e-simple/inc/google-fonts.php on line 558
    Warning: Illegal string offset ‘face’ in /homepages/45/d459633490/htdocs/wp-content/themes/e-simple/inc/google-fonts.php on line 560

    On line 558 and 560 those are code

    $google_font[‘face’],
    $google_mixed_2[‘face’] );

    So waht should i to do.

  9. Error showing on PHP 5.4.0 and PHP 5.4.0 PHP: 5.4.7
    but working fine on PHP: 5.3.18

    Warning: Illegal string offset ‘face’ in /homepages/45/d459633490/htdocs/wp-content/themes/theme/inc/google-fonts.php on line 558
    Warning: Illegal string offset ‘face’ in /homepages/45/d459633490/htdocs/wp-content/theme/e-simple/inc/google-fonts.php on line 560

    On line 558 and 560 those are code
    $google_font[‘face’],
    $google_mixed_2[‘face’] );

    please help to fix it

    1. Having same errors on PHP 5.4 with this code
      $google_font['face'],
      $google_mixed_2['face'] );

      Warning: Illegal string offset ‘face’

      Any help will be appreciated.

    2. Solved! Problem appears when you’re first time activating theme (for me it was child theme).
      I’ve changed default value with array
      this
      $google_font = of_get_option('google_font', 'Rokkitt, serif');
      with this
      $google_font = of_get_option('google_font', array( 'size' => '12px', 'face' => 'Rokkitt, serif', 'style' => 'normal', 'color' => '#5c5c5c'));
      and it works like a charm without warnings!

  10. Mel

    What i did..

    I didn’t mixed the google and system fonts. to make it work

    when a tick box was check it will show the google font then created a functions to get the font family, color, size of the font.

  11. Spacechimp

    I can’t make it enqueue the google fonts.

    I have dropdowns with all the fonts from both the google and os lists when selected the style is called but there is no link to googleapis

    I assume when i get it right something like this:

    Should appear in the header?

    My options.php file looks like this:

    the inc folder remains exactly the same as the Options Framework Theme on Github
    and I have copied

    if ( !function_exists( 'optionsframework_init' ) ) {
    define( 'OPTIONS_FRAMEWORK_DIRECTORY', get_template_directory_uri() . '/inc/' );
    require_once dirname( __FILE__ ) . '/inc/options-framework.php';
    }

    into my functions.php file.

    Any pointers would be welcome
    Thanks in advance

  12. Spacechimp

    Hi again,

    Was also wondering is it possible to set font sizes in % rather than px, I tried changing line 247 of inc/options-interface.php but it had odd effects.

    Thanks

  13. Hi Devin,

    Great theme options framework! It’s absolutely amazing!

    I’ve tested the plugin first and went as far as including the google fonts you explain in this tutorial. All went well so I decided to purchase the option theme kit so I can have the theme options without the plugin activated.
    But when I tried to paste my adapted code for google fonts it breaks the theme options dashboard (it only shows the tab headings and nothing underneath). I’ve tried even to start fresh but when I copy the first bunch of code from your above tutorial and save, it breaks again.
    Is there something I have to do different than for the plugin?

    Many thanks,
    Andreea

  14. ingegni

    Hi,
    google fonts are enqueue only if I are logged in as admin.
    Otherwise the code to include CSS don’t work.
    So what should I to do?

      1. ingegni

        I have included the code in option.php instead of functions.php
        Now I have pasted the code in functions.php and it works correctly
        thank’s

  15. zoran

    hey Devin, good stuff as always. A newb question – where would the code under System Fonts and Google Fonts be placed? Thanks man, you rock.

      1. zoran

        Thanks for the reply man. I thought that would go in functions.php and I’ve placed it there. In Theme Options instead of the 3 dropdowns with Google and System fonts I’m instead getting what looks to be the of_recognized_font_faces() array defined in options-sanitize.php instead, in all 3 dropdowns. Am I using an older version of Theme Options or missing something else? Thanks for your time.

  16. Hello Devin! Again, thanks for the great plugin!

    Quick question. I followed this tutorial and I think I put my code in all the right places. However, the inline style is outputting

    color: g;
    font-family: g;
    font-weight: g;
    font-size: g;

    Why might that be?

  17. Hi Devin,
    thank you for the awesome framework & work you still put into it. I just had a quick question about Google Fonts functionality. I have been at this for a few days, I do have it working as it should, but am ending up with about twelve of these links = (//fonts.googleapis.com/css?family=) in my head, repeating itself for every selection. I only need one link with a foreach array (I think) to print like this= font+1|font+2|font+3|font+4|font+5|font+6|font+7|font+8. I know this is very possible and your the man to do it.. I’ve tried tweaking the function typography_enqueue_google_font() but keep getting errors. Any tips would much appreciated.

    recap,
    change multiple this: //fonts.googleapis.com/css?family=
    to this: font+1|font+2|font+3|font+4

    Thanks in advance

  18. Hi
    I copy and pasted the code. It just works fine except it doesn’t load any of the google fonts. Just show default system fonts. Please help and thanks for sharing the great article
    Poonam

  19. Jason

    Love the code! Thanks

    I am trying to get some font customisation for specific fonts, or have specific styles in the dropdown.

    Like choosing ‘Lora italic 400’, without having to set the css for element to italic, which would make all fonts on the element italic.

  20. Hi Devin

    Thanks for such an amazing extensible plugin. It took me few days to understand everything to customise and fortunately I got success after spending some time. Although I purchased theme kit but I still couldn’t get what I wanted. From your resources I know how to add custom styling as inline in head section of theme, but now I want to output custom styling handled by options panel in an external file instead of inline in header. Can you share snippet of code how can I do that?

      1. Thanks for help but I don’t think I would be able to use UpThemes Framework now, because I have done a lot with your Options Framework so changing with new framework would waste a lot more time. Where I should I sent you email? I already tried to send email but never got a response.

    1. david

      you can do this fairly easily. create a php file and set the content to text/css. enqueue the file like you would a normal stylesheet. in that file, you can grab option values from the theme options. let me know if you need an example.

Leave a Reply