I am upgrading Font Awesome 4 to version 5 which introduces both integrity and crossorigin attributes to the <link rel="stylesheet"> markup.

Currently, I am using:

wp_register_style('FontAwesome', 'https://example.com/font-awesome.min.css', array(), null, 'all' );
wp_enqueue_style('FontAwesome');

Which outputs as:

<link rel="stylesheet" id="FontAwesome-css" href="https://example.com/font-awesome.min.css" type="text/css" media="all" />

With Font Awesome 5 it introduces two new attributes and values (integrity and crossorigin) e.g:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">

So I need to find out how I can add both the integrity and crossorigin to wp_register_style, I have tried but my attempts to use wp_style_add_data have failed, it would seem that this method only supports conditional, rtl and suffix, alt and title.

  • 2
    Possible duplicate of How to add extra attribute to stylesheet link? – Jacob Peattie Oct 18 at 15:36
  • Thanks @JacobPeattie, the question is a bit different but the answer given could be applicable in this case. However it dates back to 2016, maybe there's now a way that seems less hacky... – Pipo Oct 19 at 8:53
  • @Pipo I'm a WordPress developer and made a couple of WordPress plugins, I use style_loader_tag and script_loader_tag a lot to do some custom loading. Even adding defer and async to my script tags. See one of my open source plugin: github.com/Remzi1993/wp-jquery-manager – Remzi Cavdar Nov 20 at 18:52
  • @Pipo You were also right. The other post is outdated and that wouldn't work anymore. In my first example, I have showcased how you could do this with a simple string replace. I have also put a little bit more information so that other people could use this information – Remzi Cavdar Nov 20 at 20:29
  • @JacobPeattie Could you take a look? I might have some grammar errors, English is my second language – Remzi Cavdar Nov 20 at 20:33
up vote 10 down vote accepted
+50

style_loader_tag
style_loader_tag is an official WordPress API, see the documentation: https://developer.wordpress.org/reference/hooks/style_loader_tag/

apply_filters( 'style_loader_tag', $html, $handle, $href, $media )
Filters the HTML link tag of an enqueued style.


First enqueue your stylesheet, see documentation: https://developer.wordpress.org/reference/functions/wp_enqueue_style/

wp_enqueue_style( 'font-awesome-5', 'https://use.fontawesome.com/releases/v5.5.0/css/all.css', array(), null );

The $handle is 'font-awesome-5'
I do null so that there is no version number. This way it will be cached.

Simple str_replace
A simple str_replace is enough to achieve what you want, see example below

function add_font_awesome_5_cdn_attributes( $html, $handle ) {
    if ( 'font-awesome-5' === $handle ) {
        return str_replace( "media='all'", "media='all' integrity='sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU' crossorigin='anonymous'", $html );
    }
    return $html;
}
add_filter( 'style_loader_tag', 'add_font_awesome_5_cdn_attributes', 10, 2 );


Add different atributes
Below an example to add different atributes to (multiple) different stylesheets

function add_style_attributes( $html, $handle ) {

    if ( 'font-awesome-5' === $handle ) {
        return str_replace( "media='all'", "media='all' integrity='sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU' crossorigin='anonymous'", $html );
    }

    if ( 'another-style' === $handle ) {
        return str_replace( "media='all'", "media='all' integrity='blajbsf' example", $html );
    }

    if ( 'bootstrap-css' === $handle ) {
        return str_replace( "media='all'", "media='all' integrity='something-different' crossorigin='anonymous'", $html );
    }

    return $html;
}
add_filter( 'style_loader_tag', 'add_style_attributes', 10, 2 );


Add attributes to all styles
Below an example to add the same atributes to more than one stylesheet

function add_attributes_to_all_styles( $html, $handle ) {

        // add style handles to the array below
        $styles = array(
            'font-awesome-5',
            'another-style',
            'bootstrap-css'
        );

        foreach ( $styles as $style ) {
            if ( $style === $handle ) {
                return str_replace( "media='all'", "media='all' integrity='sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU' crossorigin='anonymous'", $html );
            }
        }

        return $html;
}
add_filter( 'style_loader_tag', 'add_attributes_to_all_styles', 10, 2 );




script_loader_tag
I also would like to explain the script_loader_tag, because this is also handy, but this API works in combination with wp_enqueue_script.

The script_loader_tag API is almost the same, only some small differences, see documentation: https://developer.wordpress.org/reference/hooks/script_loader_tag/

apply_filters( 'script_loader_tag', $tag, $handle, $src )
Filters the HTML script tag of an enqueued script.


Below an example to defer a single script

function add_defer_jquery( $tag, $handle ) {
    if ( 'jquery' === $handle ) {
        return str_replace( "src", "defer src", $tag );
    }
    return $tag;
}
add_filter( 'style_loader_tag', 'add_defer_jquery', 10, 2 );


Below an example to defer more than one script

function add_defer_attribute( $tag, $handle ) {

    // add script handles to the array below
    $scripts_to_defer = array(
        'jquery',
        'jquery-migrate',
        'bootstrap-bundle-js'
    );

    foreach ( $scripts_to_defer as $defer_script ) {
        if ( $defer_script === $handle ) {
            return str_replace( "src", "defer src", $tag );
        }
    }

    return $tag;
}
add_filter( 'script_loader_tag', 'add_defer_attribute', 10, 2 );

So I have explained both API's style_loader_tag and script_loader_tag. And I gave some examples for both API's I hope that this is useful for a lot of people out there. I have experience with both API's.


UPDATE
@CKMacLeod Thank you for your update, this clarifies things. We're mostly on the same page. As I said, I'm a WordPress developer and if you want to publish a theme and/or plugin on https://wordpress.org you're essentially forced to abide by the "WordPress Coding Standards" or they will simply reject your theme and/or plugin.

That's why I encourage developers out there to use "the WordPress way". I understand that sometimes there are no differences whatsoever, but it's also convenience. As you said yourself you could download Font Awesome and include it in your theme and/or plugin, this way you would only need to remove the style_loader_tag function and modify your wp_enqueue_style function.

And one last thing, in the past (5 years ago) some caching, combining and minifying plugins didn't work and most of the times I would find out why those developers who made the theme simply put things in the head in the theme and/or echoed them. Most caching plugins, who also (most of the time) provide options to combine, minify and delay execution of scripts became smarter and better at detecting bad code and working around them. But this is not preferred. That's why I encourage people to code with standards/conventions in mind.

As a developer, you always need to take into consideration what people could do with your code and taking compatibility in mind. So not taking the easy solution but the best optimal solution. I hope I have clarified my viewpoint.

EDIT
@CKMacLeod Thank you for the (technical) debate, I hope that you realize how important this is (using WordPress API's in your own development). Again, I have been looking around and even now if I look at the FAQ's of most popular minify plugins I usually see this one way or the other, for example:

Question: Why are some of the CSS and JS files not being merged?
Answer: The plugin only processes JS and CSS files enqueued using the official WordPress API method – https://developer.wordpress.org/themes/basics/including-css-javascript/ -as well as files from the same domain (unless specified on the settings).

See FAQ: https://wordpress.org/plugins/fast-velocity-minify/

  • Thanks Remzi, it does appear to be the best solution for now. Thanks for your help! – Pipo Nov 23 at 9:10
  • @Pipo You're welcome :) – Remzi Cavdar Nov 23 at 10:34
  • RC - I do think your answer may be overall better WordPress practice than mine (though I'll want to do some more research on enqueueing externally hosted scripts and files). Still, I think we should be clear on our justifications, and not oversell them, and also acknowledge that the right answer for incorporating 3rd party services may vary in different contexts. On this note, the other answer that neither of us considered, by the way, is using a good plug-in - like Better Font Awesome for FA, since they may handle updating and other tasks well. – CK MacLeod Nov 24 at 16:31
  • Yeah, you're right about using a plugin for FA. I only don't know if this is also preferred when devs create a WP theme. Usually you would want to include everything in your theme and use less plugins as possible out of the box. – Remzi Cavdar Nov 24 at 21:26

The review of script_ and style_loader_tag by @Remzi Cavdar is interesting, but, at the risk of provoking some outrage, and in the hope that someone can remind me what the advantage of using the WP queue would be in cases like this one, I'll recommend taking the easy way out, and loading Fontawesome's stylesheet via hook.

/* ADD FONTAWESOME 5.5.0 via action hook */
add_action( 'wp_head', 'sewpd_add_fontawesome' );

function sewpd_add_fontawesome() {

echo '
<!--FONTAWESOME 5.5.0 added via functions.php -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
<!--END FONTAWESOME -->
'; 

}

Some might even argue that, if you're using FA only for, say, some icons in the theme footer or within posts, you should add it lower, within the body of the page, since that way it won't come up as render-blocking, but I confess I've never done that... And I won't go as far as to recommend adding it directly to a header.php or other template file. That would be wrong. ;)

UPDATE

Remzi Cavdar was kind enough to reply to my request for a reminder as to why simply adding a Fontawesome or similar tag via wp_head() hook might be less desirable than utilizing the WordPress queue. He refers generally to the notion of best practices and somewhat more specifically to the idea that caching plugins might need to be able to access the stylesheet via the queue.

Before I go into detail, I'll say that, though I don't actually know of any significant particular justification other than that it's kind of "the WordPress Way," I like Comrade Cavdar's approach, and may use it myself in the future.

His other claims for it, however, are not persuasive to me. Maybe he or someone else can add to them. If so, I'm all ears. Bottom-line, as far as I can tell, after running over 20 tests on Pingdom and GTMetrix comparing "add via queue" vs "add via head" on a test blog, there is no significant and consistent difference in terms of graded performance, total number of page requests, or load times (e.g., "First Paint," "First Contentful Paint," and "OnLoad" at GTMetrix) between the two approaches.

Regarding caching specifically, caching plugins can't do very much with externally hosted files, whether or not they're added to the WP queue. The files themselves will remain unaffected, and your page will still generate a request for each one.

More generally, I've seen a wide range of different approaches for loading scripts and styles. Some of them will partly or entirely bypass the WP queue. It's certainly conceivable that there will be instances - a function that utilizes an array of style handles while preventing them from being loaded on particular pages, say - where having the Fontawesome or other 3rd Party Tag enqueued will be marginally useful, and that initial deploying two functions - enqueueing and filtering - will actually turn out to be more parsimonious than simply loading one.

In the case of FA, the stylesheet is already minified and is loaded via FA's own CDN. Its intrinsic impact on performance will be minimal, though, whether loaded via wp_head() or via the queue, it will still register demerits in multiple spots on performance graders - the same ones, like Google Page Speed Insights and the aforementioned GTMetrix and Pingdom, that will dock you a performance point for not saving a few bytes (not even kilobytes) re-optimizing one or another image file.

Loading via wp_head rather than the queue may trip a "correct order of scripts and styles" check (even though someone else will grade you higher for loading the externally hosted file after locally hosted ones), but, if you're really concerned about loading FA in the best possible way for your site, then you'd try locally hosting its files and sub-files, both its style and the fonts that its stylesheet calls via @font-face. In that case you could enqueue the stylesheet just like any other local file, concatenate and combine it via an optimizing plugin or directly "by hand." You could even make your own awesome modifications of Fontawesome and integrate them with your theme stylesheet and structure. Or (as earlier briefly mentioned) you could try out some more exotic performance optimization tactics like adding the CSS inline right before it was needed in the structure of a specific page.

Anyway, you wouldn't need to worry about the new "integrity" and "cross-origin" tags, and you also wouldn't have to worry if someday Fontawesome forgets to pay its CDN bill.

Or you may be working on a site that's already a complete mess under the hood, with stylesheets and scripts loaded in every which way, and it might be easier just to have your latest addition at the top of the functions.php file so you or the next developer can locate it again easily...

  • I'm curious as well, what's the downside of doing it this way, or directly adding it to a theme file? – Jersh Nov 22 at 15:52
  • Thank you for your viewpoint, the only thing is that your solution will frustrate a lot of minify and caching plugins. Like: wordpress.org/plugins/fast-velocity-minify, wordpress.org/plugins/wp-fastest-cache and etca.... – Remzi Cavdar Nov 22 at 19:02
  • 1
    The other plugins are able to manipulate the stylesheets and scripts if they are properly enqueued, if you put your code directly in the head these plugins will not be able to minify, combine and build a cache with propper order. – Remzi Cavdar Nov 22 at 19:05
  • Remzi Cavdar: Thanks for you reply, but, before I edit my answer and address the issues you raise in detail, I wonder if you have any examples of them specifically in relation to Fontawesome or generally in relation to other stylesheets like it, as in already minified and externally hosted. – CK MacLeod Nov 23 at 8:01
  • 1
    The "wordpress way" ensures maximal compatibility with plugins. Whether it is for fetching things from CDN, or removing the link for some specific pages, in your way it is just not going to be possible without actually editing the code. +1 for standing for your believes but as an answer here it is a -1 – Mark Kaplun Nov 27 at 17:16

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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