31

In a WordPress theme, how do you conditionally include scripts for ie8 and below? This is primarily to apply polyfills for various html5/css3 features. I see that wp has the $is_IE variable which can be used as a conditional to only include scripts for IE. Is there a way to add the script for only certain versions of IE though rather than all of them? This is simple with some HTML ie conditional comments, but I'd like to include the scripts all in the same place in my functions file.

Conditional for specific versions in HTML:

<!--[if lt IE 9]> <script src="iepolyfill.min.js"></script> <![endif]-->

Conditional for all IE in WP:

    global $is_IE;

    if ( $is_IE ) {
        wp_enqueue_script( 'iepolyfill', bloginfo('stylesheet_directory').'/js/iepolyfill.min.js' );
    }

I've looked around and mainly find details about conditional scripts for wp backend only.

Any suggestions?

Ahmad Awais
  • 33,440
  • 5
  • 74
  • 56
circlecube
  • 706
  • 1
  • 10
  • 19

7 Answers7

74

For WordPress 4.2+

Use wp_script_add_data to wrap the script in a conditional comment:

wp_enqueue_script( 'html5shiv', '//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.js' );
wp_script_add_data( 'html5shiv', 'conditional', 'lt IE 9' );

wp_enqueue_script( 'respond', get_template_directory_uri() . '/js/respond.min.js' );
wp_script_add_data( 'respond', 'conditional', 'lt IE 9' );

Just make sure you register the script before invoking wp_script_add_data (registering is handled by wp_enqueue_script above), and that the first argument you pass to wp_script_add_data matches the first argument you passed when you registered the script.


For WordPress 4.1

You can use the script_loader_tag filter today to enqueue scripts wrapped in conditional comments. Here’s an example implementation:

wp_enqueue_script( 'html5shiv', '//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.js', array(), '3.7.2', false );
add_filter( 'script_loader_tag', function( $tag, $handle ) {
    if ( $handle === 'html5shiv' ) {
        $tag = "<!--[if lt IE 9]>$tag<![endif]-->";
    }
    return $tag;
}, 10, 2 );

And if you want to include more than one script in the same way, you can use something like:

// Conditional polyfills
$conditional_scripts = array(
    'html5shiv'           => '//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.js',
    'html5shiv-printshiv' => '//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv-printshiv.js',
    'respond'             => '//cdn.jsdelivr.net/respond/1.4.2/respond.min.js'
);
foreach ( $conditional_scripts as $handle => $src ) {
    wp_enqueue_script( $handle, $src, array(), '', false );
}
add_filter( 'script_loader_tag', function( $tag, $handle ) use ( $conditional_scripts ) {
    if ( array_key_exists( $handle, $conditional_scripts ) ) {
        $tag = "<!--[if lt IE 9]>$tag<![endif]-->";
    }
    return $tag;
}, 10, 2 );
Andrew Patton
  • 5,344
  • 3
  • 30
  • 30
  • I found this answer through Google as I was facing the same problem as the OP. It's a great answer, but even the example using an anonymous function isn't that great because you don't properly load the script through Wordpress. Depending on the plugins you use this can lead to issues because perhaps you load the same script twice, so always have an eye at the HTML that Wordpress actually prints. – Sven Sep 20 '13 at 19:23
  • I think this is okay, but it's really no better than just hard coding them in the header.php file, imo. – Mulan May 13 '14 at 09:37
  • @naomik It depends on how you like to structure your theme. If you don’t leverage wp_enqueue_script or wp_enqueue_style in your theme and you only have one header.php file, then it makes a lot of sense to group your script/css includes in header.php. But if, for example, you do use the enqueue functions to manage your includes, it is very helpful to centralize the script/style includes in one single place. This approach facilitates that. – Andrew Patton May 14 '14 at 16:02
  • @BramVanroy Absolutely. – Andrew Patton Feb 10 '15 at 15:07
  • 1
    Looks like this is going to be part of 4.2! https://core.trac.wordpress.org/ticket/16024 – Kyle Ridolfo Mar 06 '15 at 19:43
  • 1
    Was this added in 4.2? – Neil May 14 '15 at 09:17
  • @Neil The `script_loader_tag` was added in 4.1. Support for `$wp_scripts->add_data( 'html5shiv', 'conditional', 'lt IE 9' );` was added in 4.2. – Andrew Patton May 14 '15 at 16:02
  • Can somebody greatly dumb down and provide a full working code example of how I'm supposed to implement whatever 4.2 is supporting? – Clarus Dignus Jan 23 '16 at 07:55
  • 1
    @ClarusDignus I added an example of the WP 4.2+ version of loading scripts with conditional comments. Does that make it clear, or do you still have questions? – Andrew Patton Jan 24 '16 at 19:49
  • @AndrewPatton The edit is clear and understood. Thanks for taking the time to apply the edit. – Clarus Dignus Jan 24 '16 at 20:53
24
  • You should use wp_register_script() whenever you add scripts to your WP themes or plugins.
  • Server side sniffing is generaly bad idea, because it's unsure.
  • Usually you want to target browsers lacking sertain features, not necessarily only IE browser. Modernzr is good scripts to do just that.

For IE, conditional tags work very well. Here's how you can add conditional tags into a script, example is for HTML5shiv:

global $wp_scripts;
wp_register_script( 
    'html5shiv', 
    get_bloginfo('template_url').'/assets/js/html5shiv.js', 
    array(), 
    '3.6.2'
    );
$wp_scripts->add_data( 'html5shiv', 'conditional', 'lt IE 9' );
Mikael Korpela
  • 460
  • 4
  • 9
8

Solution for WordPress 4.2 and above

The correct way would be to apply wp_enqueue_script since it JavaScripts here, and not css styles. Also, it is better to use get_bloginfo('stylesheet_url') to make sure this also works in Child Themes.

/**
 * IE Fallbacks
 */

function load_IE_fallback() {
    wp_register_script( 'ie_html5shiv', get_bloginfo('stylesheet_url'). '/js/html5shiv.min.js', __FILE__, false, '3.7.2' );
    wp_enqueue_script( 'ie_html5shiv');
    wp_script_add_data( 'ie_html5shiv', 'conditional', 'lt IE 9' );

    wp_register_script( 'ie_respond', get_bloginfo('stylesheet_url'). '/js/respond.min.js', __FILE__, false, '1.4.2' );
    wp_enqueue_script( 'ie_respond');
    wp_script_add_data( 'ie_respond', 'conditional', 'lt IE 9' );
}
add_action( 'wp_enqueue_scripts', 'load_IE_fallback' ); 
Daniel Klose
  • 335
  • 1
  • 4
  • 18
  • I was about to add the exact same thing myself, but I see you've already done it. I've tested this and it works for me with `get_template_directory_uri().'/js/lib/excanvas.js'` in my theme's functions.php – vahanpwns Jul 31 '15 at 20:47
  • Thanks for providing this answer. Nothing irks me more than when the questioner finds an answer but doesn't bother to break it down for others. – Clarus Dignus Jan 23 '16 at 07:58
8

Update for WordPress 4.7.3 with scripts loading from CDN:

    add_action( 'wp_enqueue_scripts', 'load_IE_fallback' );
function load_IE_fallback() {
    wp_register_script( 'ie_html5shiv', 'https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js', '', '3.7.3', false );
    wp_register_script( 'ie_respond', 'https://oss.maxcdn.com/respond/1.4.2/respond.min.js', '', '1.4.2', false );

    wp_enqueue_script( 'ie_html5shiv');
    wp_enqueue_script( 'ie_respond');

    wp_script_add_data( 'ie_html5shiv', 'conditional', 'lt IE 9' );    
    wp_script_add_data( 'ie_respond', 'conditional', 'lt IE 9' );
}
2

The best way to do it is enqueue the scripts and then use wp_style_add_data() to put conditional. This method is being used by official themes like twenty thirteen

There is an answer similar to this but he adds extra if in the condition which is wrong.

wp_register_style( 'ie_html5shiv', get_template_directory_uri() . '/js/html5shiv.js' );
    wp_enqueue_style( 'ie_html5shiv');
    wp_style_add_data( 'ie_html5shiv', 'conditional', 'lt IE 9' );

    wp_register_style( 'ie_respond', get_template_directory_uri() . '/js/respond.min.js' );
    wp_enqueue_style( 'ie_respond');
    wp_style_add_data( 'ie_respond', 'conditional', 'lt IE 9' );
Ahmad Awais
  • 33,440
  • 5
  • 74
  • 56
1

As wordpress is a PHP script, it can access server variable via $_SERVER

Then you can search for detect browser with PHP, PHP: If internet explorer 6, 7, 8 , or 9

Community
  • 1
  • 1
James
  • 13,571
  • 6
  • 61
  • 83
  • 10
    Incomplete answer. This does not address how to actually inject a conditional around a script using `wp_enqueue_script`, the prescribed way of adding javascript to your theme. – Mulan May 13 '14 at 09:35
1

Try to use the wp_style_add_data() function (officially used in twentythirteen and twentyfourteen theme:

wp_enqueue_style( 'iepolyfill', bloginfo( 'stylesheet_directory' ) . '/js/iepolyfill.min.js' );
wp_style_add_data( 'iepolyfill', 'conditional', 'if lt IE 9' );

Update: Since WordPress >= 4.2.0 there is a function that is used in the same way. It's called:

wp_script_add_data()
Flow
  • 365
  • 3
  • 7
  • Have you confirmed that there are no unintended or negative consequences to using the `wp_style` logic for adding JavaScript? Does it add the file as a ` – Andrew Patton Sep 03 '14 at 14:45
  • 2
    This code generates HTML to include a CSS file, not Javascript. – Maxime Dec 28 '14 at 17:36