Customizer – How to live update @font-face?

I am using customizer to select from my own hosted fonts, and it works pretty well. The only thing I can’t figure out is how to use postMessage for the live preview. Here’s what I currently have:

Customizer control / setting

<?php
function site_title_font( $controls ) {

$controls[] = array(
'priority' => 1,
'type' => 'select',
'setting' => 'site_title_font',
'label' => __( 'Site Title Font', 'alphatest' ),
'section' => 'site_title_font_section',
'transport' => 'postMessage',
'default' => 'default',
'choices' => include (get_template_directory() . '/customizer/fonts/groovy-fonts.txt')
);

return $controls;
}
add_filter( 'kirki/controls', 'site_title_font' );
?>

fontface.php ouputs the css

<?php
if ( get_theme_mod( site_title_font ) ) {
echo'@font-face {
font-family: ' . get_theme_mod( site_title_font ) . ';
src: url('/media/fonts2/' . get_theme_mod( site_title_font ) . '/webfont.woff2') format('woff2'),
url('/media/fonts2/' . get_theme_mod( site_title_font ) . '/webfont.woff') format('woff');
}';
}
?>

JavaScript:

( function( $ ) {
wp.customize( 'site_title_font', function( value ) {
value.bind( function( to ) {
$( 'font-family' ).css( to );
} );
} );
} )( jQuery );

Output after saving

<style>
@font-face {
font-family: a780-deco-regular;
src: url('/media/fonts2/a780-deco-regular/webfont.woff2') format('woff2'),
url('/media/fonts2/a780-deco-regular/webfont.woff') format('woff');
}

h1.site-title,
p.site-title a {
font-family: a780-deco-regular;
font-weight: 300;
}
</style>

Please note that the css is “after” saving. If I remove ‘transport’ => ‘postMessage’ from the customize setting, everything works fine but the page has to refresh with each font change — and I have a LOT of fonts :slight_smile: . I just can’t figure out how to get the JavaScript to work. I think the issue is having to update both @font-face and the .site-title css at the same time. Any ideas?

Thanks

  • calvinrogercanas
    • New Recruit

    Hi @Tedster,

    Thanks for reaching us.

    I think you are correct on most of your javascript code. Just tell the javascript the html element you want(by the classname) to implement the font then declaring .css function of jquery by putting parameters of the css rule you want. This code may be the fix you want.

    ( function( $ ) {
    wp.customize( 'site_title_font', function( value ) {
    value.bind( function( to ) {
    $( '.site-title' ).css( 'font-family', to ? to : '' );
    } );
    } );
    } )( jQuery );

    What it does is when the theme customizer field of ‘site_title_font’ change it will find the html element with a class name of .site-title then apply the font-family: Arial; for example but in real case the font you choose.

    Hope it makes sense to you. If it still doesn’t work then I may need to access your dashboard and theme files thru ftp so.

    Can you please send in:

    – In the subject field add “Attn:Calvin Canas”

    – Link back to this thread

    – Include admin/network access + login url (this way you don’t need to bother enabling over and over the support access when it expires.)

    – Include FTP

    – Include any relevant URLS for your site

    On the contact form, select “I have a different question“, this ensures it comes through and gets assigned to me.

    https://premium.wpmudev.org/contact/

    Kind Regards,

    Calvin

  • Tedster
    • The Incredible Code Injector

    Hi Calvin, thanks for the reply.

    Targeting the font-family element using .site-title class is not the issue. What I’m having trouble with is targeting the @font-face element. The following code will change the .site-title:

    ( function( $ ) {
    wp.customize( 'site_title_font', function( value ) {
    value.bind( function( to ) {
    $( '.site-title a, site-title' ).css( to );
    } );
    } );
    } )( jQuery );

    But the font won’t load if I don’t also change the @font-face element. When I try the following code:

    ( function( $ ) {
    wp.customize( 'site_title_font', function( value ) {
    value.bind( function( to ) {
    $( '@font-face, .site-title a, site-title' ).css( to );
    } );
    } );
    } )( jQuery );

    I get the following error using Chrome code inspector.

    Uncaught Error: Syntax error, unrecognized expression: @font-face, .site-title a, site-title

    I also tried escaping the @ character with @ but that made no difference… still got the same error.

    Basically, I can target font-family here:

    h1.site-title,
    p.site-title a {
    font-family: abottoldstyle-regular;
    font-weight: 300;
    }

    but I don’t know how to target font-family here:

    @font-face {
    font-family: abottoldstyle-regular;
    src: url('/media/fonts2/abottoldstyle-regular/webfont.woff2') format('woff2'),
    url('/media/fonts2/abottoldstyle-regular/webfont.woff') format('woff');
    }

    So I guess my question is how do I target the @font-face element?

    Sorry I can’t provide ftp or login access at this time, as I’m working from my home computer. If need be, I can put the site online so you can access it, but if I just know how to target the @font-face element I’ll probably be okay from there.

  • Tedster
    • The Incredible Code Injector

    Hey folks, I’m still trying to figure out how to target the @font-face element. I’m studying up on JavaScript and jQuery, hoping to find a solution while learning, but if anybody knows the proper way to do

    ( function( $ ) {
    wp.customize( '@font-face, site_title_font', function( value ) {
    value.bind( function( to ) {
    $( '.site-title' ).css( 'font-family', to ? to : '' );
    } );
    } );
    } )( jQuery );

    without getting an error, it would really help me move forward.

    Thanks

  • calvinrogercanas
    • New Recruit

    Hi @Tedster,

    Thanks for your reply and sorry for the delay.

    What you need to do is pre-load the font you will use by declaring the font-face in a css file that is included on the site. Then you just need to put a css rule that will change the element font like this:

    h1.site-title,
    p.site-title a {
    font-family: abottoldstyle-regular;
    font-weight: 300;
    }

    Sorry but I didn’t quite understand this:

    fontface.php ouputs the css

    <?php
    if ( get_theme_mod( site_title_font ) ) {
    echo'@font-face {
    font-family: ' . get_theme_mod( site_title_font ) . ';
    src: url('/media/fonts2/' . get_theme_mod( site_title_font ) . '/webfont.woff2') format('woff2'),
    url('/media/fonts2/' . get_theme_mod( site_title_font ) . '/webfont.woff') format('woff');
    }';
    }
    ?>

    Could you tell me the output value of this get_theme_mod( site_title_font );

    Looking forward for your reply! :slight_smile:

    Kind Regards,

    Calvin

  • Tedster
    • The Incredible Code Injector

    Thanks for not giving up on this :slight_smile: .

    It would be so much easier to link to a separate .css file to pre-load the fonts, but there are about 600 of them. Am I correct in assuming the browser will load all the fonts?

    In answer to your question,

    get_theme_mod( site_title_font );

    outputs fonts from a select list, which is populated with the following…

    <?php
    return array(
    '' => '- Default -',
    'a-charming-font-expanded' => 'A Charming Font',
    'a-cut-above-the-rest' => 'A Cut Above',
    'a-yummy-apology' => 'A Yummy Apology',
    'a780-deco-regular' => 'A780 Deco',
    'a850-deco-regular' => 'A850 Deco',
    'abberancy-regular' => 'Abberancy',
    ...
    'lupus-blight' => 'Lupus Blight',
    'lymphnodes' => 'Lymphnodes',
    'lynx-brk' => 'Lynx',
    );

    The list is actually much, much longer. In the case of “A Charming Font”, the out put would be “a-charming-font-expanded”.

    Maybe there is an easier way. As I’m reading up on JavaScript, I see there is a method to “add” html. I’m thinking maybe I can add the @font-face element after the <style> tag, something like so…

    function(add_font_face_code) {
    var = myVarThingy(get_theme_mod( site_title_font ));
    $("style").after("@font-face {
    font-family: myVarThingy;
    src: url('/media/groovy-fonts/myVarThingy/webfont.woff2') format('woff2'),
    url('/media/groovy-fonts/myVarThingy/webfont.woff') format('woff');
    }");
    }

    The mess above is my best guess at what the JavaScript might look like but, as you can see, I have no idea what I’m doing. Hopefully it is enough to show what I’m aiming for. Basically, it would end up looking like this…

    <style>
    @font-face {
    font-family: a780-deco-regular;
    src: url('/media/groovy-fonts/a780-deco-regular/webfont.woff2') format('woff2'),
    url('/media/groovy-fonts/a780-deco-regular/webfont.woff') format('woff');
    }

    h1.site-title {
    font-family: a780-deco-regular;
    }

    </style>

  • calvinrogercanas
    • New Recruit

    Hi @Tedster,

    No worries, happy to help you in anyway :slight_smile:

    I found a plugin that does this: https://wordpress.org/plugins/font-customizer/ perhaps your preferred fonts are there. Also, I will suggest you provide the theme’s source code so I can fully look at it.

    I will call our Second-Line Support(coding experts) if I still can’t provide a solution for it.

    Looking forward for your reply! :slight_smile:

    Kind Regards,

    Calvin

  • Tedster
    • The Incredible Code Injector

    I have the premium version of that plugin and tried to decipher how it does the ajax, but it’s beyond me. :slight_smile: It’s a nice plugin for what it is. I can’t use it for a couple of reasons — unwitting users will use 20 different fonts, and I don’t want to use google fonts for this particular purpose.

    I can put the site online today and give you access. I figured out how to ajaxify everything else, it’s just the @font-face that has me stumped. It would be awesome if you could figure out a way to make it work.

  • Tedster
    • The Incredible Code Injector

    Calvin, I installed WP on a separate site which I’m not using, along with only the relevant files. That way you don’t have to dig through the mess I made while trying to figure this and some other stuff out., and I can keep on working on other stuff. Feel free to modify and edit as you please. I sent you a message with all the details. Have fun! :p

  • calvinrogercanas
    • New Recruit

    Hi @Tedster,

    Thanks for your reply.

    Ha, I spent quite a long time for this. I might have the solution for this but unfortunately I didn’t receive the message so.

    Can you please send in:

    – In the subject field add “Attn:Calvin Canas”

    – Link back to this thread

    – Include admin/network access + login url (this way you don’t need to bother enabling over and over the support access when it expires.)

    – Include FTP

    – Include any relevant URLS for your site

    On the contact form, select “I have a different question“, this ensures it comes through and gets assigned to me.

    https://premium.wpmudev.org/contact/

    I rely on this documentation page: https://codex.wordpress.org/Theme_Customization_API. Hopefully it will work.

    Looking forward for your reply! :slight_smile:

    Kind Regards,

    Calvin

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.