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" rel="nofollow noreferrer noopener" 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" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" 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.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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( 'script_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/
Method 2
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" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" 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…
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0