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.
Awesome! thanks Devin.
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?
Huh, yeah. It looks like Rockitt has disappeared. Thanks for mentioning that.
And, weird, it’s back:
http://www.google.com/webfonts/specimen/Rokkitt
Awesome! What about sanitation? it will be sanitized as well as typography default option?
Yes.
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?
There’s no way I know of to do that programmatically. You’ll just have to do if else statements to load the custom font weights.
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 );
}
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
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
Hi Lukas. You’re referring to the part under “Loading the Google Font”. The actual google fonts get loaded with that wp_enqueue_style call. You can put that code in functions.php, or any other file you’ve included from functions.php.
Is there a way to actually load the fonts dynamically or fo you have to manually list each one??
There is an API to get all the fonts, but it seems a bit clunky for actually loading that into an option. And it’s difficult to output since the naming isn’t consistent. So, yes, I recommend curating a list of fonts you want for the theme, and only displaying those.
Thanks for posting. Looking at building Google webfonts into a new theme and this has been invaluable.
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 :)
There is way to dynamically get a list of all Google fonts, but it requires an API key. My guess is that most developers who include hundreds of fonts pull those down with a script and convert them into an option programmatically. My best suggestion would be to download one of them and see how they do it.
This plugin, for instance, says they push updates as new fonts are released:
http://wordpress.org/extend/plugins/wp-google-fonts/
Here’s some information on the API: https://developers.google.com/webfonts/docs/developer_api
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.
Is there a good way to show a distinction between Google and system fonts. So that in the drop down it is obvious which is which.
Thanks
You could give system fonts an asterisk (*), and in the description explain what that means.
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
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
Hi Mel. As far as I know the code is good. You could try doing some debugging (try a var_dump of the array) to see if you can track down why that field isn’t getting filled.
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!
You mean to see the font in the options panel? I haven’t built a way to do that, though you are welcome to add it in yourself. There’s also the UP Theme Options Framework, which I believe allows you to do this.
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
It’s covered under “Setting the Font Style” in this post. You’d output an inline style.
Ok – so should this be included in the functions.php ? i’m having no luck with getting it to output the inline styles.
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.
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
Are you using the version purchased in the Options Kit with no customizations and getting that error? If so, glad to dive in. If not, you likely have a bug in your code. I’d var_dump all the arrays to see how they are filling.
NO it’s your code that you give in this article
[Code Redacted]
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.
var_dump them and make sure they have the values you expect.
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!
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.
Made some tweaks, but this works great. Thanks!
But its not working on PHP 5.4.0. Showing error on two lines.
Wrote above. Works on PHP5.4 without warnings.
Hope it will help.
Cheers
I’m sorry, I want to draw the fonts in the theme, such as dynamically set the font page?
thanks :)
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
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
Yes, this option isn’t ideal. Changing it directly there is fine. You can also use the of_recognized_font_sizes filter.
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
No, code is pretty much the same. Do you have WP_DEBUG on so you can see where the error is happening?
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?
Are you sure you used http://codex.wordpress.org/Function_Reference/wp_enqueue_script. This should only load scripts on the user side (not admin side).
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
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.
functions.php or a file that you include from functions.php.
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.
That should all work. Have you looked at the version in the Options Kit? That might be helpful.
I should check that out. I’ll grab the Options Kit and go from there. Thanks man
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?
Looks like it’s not being output correctly. Can you var_dump the array and see the saved values?
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
Sure. You’ll want too get all the font families into a single array, and then explode the array with a pipe delimiter.
$fonts = array( 'font-1, 'font-2', 'font-3', font-4' );
$link = '//fonts.googleapis.com/css?family=' . explode("|", $fonts);
See: http://us3.php.net/explode
Sorry, it printed like this: with Array at end of the first font.
Hi Tony. Can you post this in pastebin and then e-mail me the link (use the contact form). Difficult to follow with code in comments.
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
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.
I’m not sure I understand the question. If you are applying a font to a specific element, can’t you also apply a specific styling to just that element?
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?
Take a look at the UpThemes Framework, they have a built in way to write out to an external file. If you end up going with that, just ping via e-mail and I can get you a refund on the Kit.
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.
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.