11

Enqueuing Google Web Fonts the usual way, i.e., using the wp_enqueue_style function like so...

function wpse_google_webfonts() {
    wp_enqueue_style( 'google-webfonts', 'http://fonts.googleapis.com/css?family=Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700' );
}
add_action( 'wp_enqueue_scripts', 'wpse_google_webfonts' );

...results in a link tag placed in the header like so:

<link rel='stylesheet' id='google-webfonts-css'  href='http://fonts.googleapis.com/css?family=Ubuntu+Condensed%7COpen+Sans%3A400italic%2C700italic%2C400%2C700&#038;ver=3.5' type='text/css' media='all' />

As you can see, the resultant URL is encoded.

I am pretty sure it poses no problems, but to keep things clean and clear, I would like to go ahead and ask -- Is there a way to enqueue Google Web Fonts (via functions.php and not a plugin) in a way that the URL output is not encoded?

That's like so:

<link rel='stylesheet' id='google-webfonts-css'  href='http://fonts.googleapis.com/css?family=Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700?ver=3.5' type='text/css' media='all' />

Reason For Bounty

@webaware's answer is near perfect, especially because it's similar to the method employed in enqueuing 'Open Sans' Google Web Font in the Twenty Twelve theme.

The only problem in the output is that it's like this:

<link rel='stylesheet' id='twentytwelve-fonts-css'  href='http://fonts.googleapis.com/css?family=Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700&#038;subset=latin,latin-ext' type='text/css' media='all' />

Notice the &#038;? It should be &, otherwise the font-files served only have the latin glyphs (i.e. the subset parameter in the URL is neglected unless you use & and NOT its HTML entity).

Anyone who can help modify @webaware's answer so that the output's looks like this...

<link rel='stylesheet' id='twentytwelve-fonts-css'  href='http://fonts.googleapis.com/css?family=Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700&subset=latin,latin-ext' type='text/css' media='all' />

...wins the bounty.

1
  • Not quite sure what you're wanting here; do you want to have latin + latin-ext subsets (which this does), or do you want it not to subset (which can be achieved by removing the 'subset' element from the array)?
    – webaware
    Commented Dec 30, 2012 at 7:22

4 Answers 4

24
+50

WordPress knows what it is doing here. Honest.

When rendering an ampersand in HTML, you should always use &amp; or &#038;. The browser then converts it to & before actually firing the HTTP request. See for yourself by inspecting the network calls in a web inspector tool. You're not actually losing your non-latin subsets.

Notice the &#038;? It should be &, otherwise the font-files served only have the latin glyphs (i.e. the subset parameter in the URL is neglected unless you use & and NOT its HTML entity).

This tells me you have inspected the source to see that there is an escaped ampersand, without actually verifying the resulting behavior. Yes, it occurs when you paste a URL with an escaped ampersand in an address bar. But not when you have a properly encoded and escaped URL in an HTML src or href attribute.

You should look over http://www.blooberry.com/indexdot/html/topics/urlencoding.htm for additional unsafe and reserved characters. Both groups should always be encoded.

5
  • 1
    A very fine explanation, thanks for taking the time Andrew!
    – webaware
    Commented Dec 30, 2012 at 7:23
  • So, you are saying... when you have a properly encoded URL in an HTML src or href attribute (i.e. http://fonts.googleapis.com/css?family=Ubuntu+Condensed&#038;subset=latin,latin-ext), the way the browser treats it is equivalent to the user entering http://fonts.googleapis.com/css?family=Ubuntu+Condensed&subset=latin,latin-ext (i.e. with the actual & and not the HTML entity) in the address bar. Is that correct? If so, thanks for the clear explanation. :)
    – its_me
    Commented Dec 30, 2012 at 7:58
  • 2
    Correct. I edited my answer slightly to make it a bit more clear. In this case, the ampersand is an escaped HTML entity, not URL encoded. It should not be encoded (which would be %38) because it is being used in its special URL role. URL encoding a reserved or unsafe character like |, :, or spaces are separate, and also encouraged. Commented Dec 30, 2012 at 8:16
  • @AndrewNacin: just a nitput, but: that URL to blooberry.com is actually about URL-encoding characters, not HTML-encoding characters. The issue you are addressing is the latter, not the former.
    – webaware
    Commented Dec 30, 2012 at 8:47
  • I spoke about both in my answer, and comment. You were worried about both in your original question. Commented Dec 30, 2012 at 21:47
5

Try this (will also handle HTTP vs HTTPS):

function wpse_google_webfonts() {
    $protocol = is_ssl() ? 'https' : 'http';
    $query_args = array(
        'family' => 'Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700',
        'subset' => 'latin,latin-ext',
    );

    wp_enqueue_style('google-webfonts',
        add_query_arg($query_args, "$protocol://fonts.googleapis.com/css" ),
        array(), null);
}

add_action( 'wp_enqueue_scripts', 'wpse_google_webfonts' );
3
  • By chance, is this based on Twenty Twelve theme? :P
    – its_me
    Commented Dec 26, 2012 at 14:30
  • Very likely where I saw it :) but It's all just part of the kit now.
    – webaware
    Commented Dec 26, 2012 at 14:31
  • 1
    Actually, they are the same. The browser sees &#038; as & and loads exactly the same URI. To test, I loaded simple HTML pages with both, and cleared cache before loading; both loaded the same font files (same size). Try it.
    – webaware
    Commented Dec 30, 2012 at 7:19
2

Based on this answer you could try something like this untested code:

add_filter( 'clean_url', 'wpse_77227_decode_googlefont_url' );

function wpse_77227_decode_googlefont_url( $url )
{
    $host = parse_url ($url, PHP_URL_HOST );

    if ( 'fonts.googleapis.com' === $host )
        return urldecode( $url );

    return $url;
}
8
  • Yes, it kinda works, except the way versioning is done (wrongly?). Output looks like: <link rel='stylesheet' id='google-webfonts-css' href='http://fonts.googleapis.com/css?family=Ubuntu Condensed|Open Sans:400italic,700italic,400,700&#038;ver=3.5' type='text/css' media='all' /> -- notice &#038;ver=3.5? It should rather be ?ver=3.5. Any fix in mind? Thanks for the answer. :)
    – its_me
    Commented Dec 25, 2012 at 16:53
  • You cannot use a second ?. That would result in an invalid URL for Google.
    – fuxia
    Commented Dec 25, 2012 at 16:57
  • http://fonts.googleapis.com/css?family=Ubuntu%20Condensed|Open%20Sans:400italic,700italic,400,700?ver=3.5 is loading up just fine. Or am I missing your point?
    – its_me
    Commented Dec 25, 2012 at 17:00
  • The argument separator is &, not ?. You cannot rely on Google’s generosity.
    – fuxia
    Commented Dec 25, 2012 at 21:25
  • This function has been deprecated "clean_url" -> codex.wordpress.org/Function_Reference/clean_url, you should use other one.
    – Ed T.
    Commented Dec 25, 2012 at 23:14
1

Actually, it's as simple as this:

wp_enqueue_style( 'google-webfonts', 'http://fonts.googleapis.com/css?family=Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700&subset=latin,latin-ext', array(), null );

And that should output:

<link rel='stylesheet' id='google-webfonts-css'  href='http://fonts.googleapis.com/css?family=Ubuntu+Condensed|Open+Sans:400italic,700italic,400,700&#038;subset=latin,latin-ext' type='text/css' media='all' />

That's pretty close to what I'd wanted (only regret being that & becomes &#038; in output). But then I realized it doesn't matter, really, largely thanks to Andrew Nacin's answer.

But I must thank everyone for their efforts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.