The Developer’s Guide To Conflict-Free JavaScript And CSS In WordPress
Imagine you’re playing the latest hash-tag game on Twitter when you see this friendly tweet:
You might want to check your #WP site. It includes two copies of jQuery. Nothing’s broken, but loading time will be slower.
You check your source code, and sure enough you see this:
<script src="/wp-includes/js/jquery/jquery.js?ver=1.6.1" type="text/javascript"></script>
<script src="/wp-content/plugins/some-plugin/jquery.js"></script>

What Went Wrong?
The first copy of jQuery is included the WordPress way, while some-plugin includes jQuery as you would on a static HTML page.
A number of JavaScript frameworks are included in WordPress by default, including:
- Scriptaculous,
- jQuery (running in noConflict mode),
- the jQuery UI core and selected widgets,
- Prototype.
A complete list can be found in the Codex. On the same page are instructions for using jQuery in noConflict mode.
Avoiding the Problem
WordPress includes these libraries so that plugin and theme authors can avoid this problem by using the wp_register_script and wp_enqueue_script PHP functions to include JavaScript in the HTML.
Registering a file alone doesn’t do anything to the output of your HTML; it only adds the file to WordPress’s list of known scripts. As you’ll see in the next section, we register files early on in a theme or plugin where we can keep track of versioning information.
To output the file to the HTML, you need to enqueue the file. Once you’ve done this, WordPress will add the required script tag to the header or footer of the outputted page. More details are provided later in this article.
Registering a file requires more complex code than enqueueing the files; so, quickly parsing the file is harder when you’re reviewing your code. Enqueueing the file is far simpler, and you can easily parse how the HTML is being affected.
For these techniques to work, the theme’s header.php file must include the line <?php wp_head(); ?> just before the </head> tag, and the footer.php file must include the line <?php wp_footer(); ?> just before the </body> tag.
Registering JavaScript
Before registering your JavaScript, you’ll need to decide on a few additional items:
- the file’s handle (i.e. the name by which WordPress will know the file);
- other scripts that the file depends on (jQuery, for example);
- the version number (optional);
- where the file will appear in the HTML (the header or footer).
This article refers to building a theme, but the tips apply equally to building a plugin.
Examples
We’ll use two JavaScript files to illustrate the power of the functions:
The first is base.js, which is a toolkit of functions used in our example website.
function makeRed(selector){
var $ = jQuery; //enable $ alias within this scope
$(function(){
$(selector).css('color','red');
});
}
The base.js file relies on jQuery, so jQuery can be considered a dependency.
This is the first version of the file, version 1.0.0, and there is no reason to run this file in the HTML header.
The second file, custom.js, is used to add the JavaScript goodness to our website.
makeRed('*');
This custom.js file calls a function in base.js, so base.js is a dependency.
Like base.js, custom.js is version 1.0.0 and can be run in the HTML footer.
The custom.js file also indirectly relies on jQuery. But in this case, base.js could be edited to be self-contained or to rely on another framework. There is no need for jQuery to be listed as a dependency of custom.js.
It’s now simply a matter of registering your JavaScript using the function wp_register_script. This takes the following arguments:
$handle
A string$source
A string$dependancies
An array (optional)$version
A string (optional)$in_footer
True/false (optional, default is false)
When registering scripts, it is best to use the init hook and to register them all at once.
To register the scripts in our example, add the following to the theme’s functions.php file:
function mytheme_register_scripts() {
//base.js – dependent on jQuery
wp_register_script(
'theme-base', //handle
'/wp-content/themes/my-theme/base.js', //source
array('jquery'), //dependencies
'1.0.0', //version
true //run in footer
);
//custom.js – dependent on base.js
wp_register_script(
'theme-custom',
'/wp-content/themes/my-theme/custom.js',
array('theme-base'),
'1.0.0',
true
);
}
add_action('init', 'mytheme_register_scripts');
There is no need to register jQuery, because WordPress already has. Re-registering it could lead to problems.
You Have Achieved Nothing!
All of this registering JavaScript files the WordPress way has, so far, achieved nothing. Nothing will be outputted to your HTML files.
To get WordPress to output the relevant HTML, we need to enqueue our files. Unlike the relatively long-winded commands required to register the functions, this is a very simple process.
Outputting the JavaScript HTML
Adding the <script> tags to your HTML is done with the wp_enqueue_script function. Once a script is registered, it takes one argument, the file’s handle.
Adding JavaScript to the HTML is done in the wp_print_scripts hook with the following code:
function mytheme_enqueue_scripts(){
if (!is_admin()):
wp_enqueue_script('theme-custom'); //custom.js
endif; //!is_admin
}
add_action('wp_print_scripts', 'mytheme_enqueue_scripts');
Of our two registered JavaScript files (base.js and custom.js), only the second adds JavaScript functionality to the website. Without the second file, there is no need to add the first.
Having enqueued custom.js for output to the HTML, WordPress will figure out that it depends on base.js being present and that base.js, in turn, requires jQuery. The resulting HTML is:
<script src="/wp-includes/js/jquery/jquery.js?ver=1.6.1" type="text/javascript"></script>
<script src="/wp-content/themes/my-theme/base.js?ver=1.0.0" type="text/javascript"></script>
<script src="/wp-content/themes/my-theme/custom.js?ver=1.0.0" type="text/javascript"></script>
Registering Style Sheets
Both of the functions for adding JavaScript to our HTML have sister PHP functions for adding style sheets to the HTML: wp_register_style and wp_enqueue_style.
As with the JavaScript example, we’ll use a couple of CSS files throughout this article, employing the mobile-first methodology for responsive Web design.
The mobile.css file is the CSS for building the mobile version of the website. It has no dependencies.
The desktop.css file is the CSS that is loaded for desktop devices only. The desktop version builds on the mobile version, so mobile.css is a dependency.
Once you’ve decided on version numbers, dependencies and media types, it’s time to register your style sheets using the wp_register_style function. This function takes the following arguments:
$handle
A string$source
A string$dependancies
An array (optional, default is none)$version
A string (optional, the default is the current WordPress version number)$media_type
A string (optional, the default is all)
Again, registering your style sheets using the init action is best.
To your theme’s functions.php, you would add this:
function mytheme_register_styles(){
//mobile.css for all devices
wp_register_style(
'theme-mobile', //handle
'/wp-content/themes/my-theme/mobile.css', //source
null, //no dependencies
'1.0.0' //version
);
//desktop.css for big-screen browsers
wp_register_style(
'theme-desktop',
'/wp-content/themes/my-theme/desktop.css',
array('theme-mobile'),
'1.0.0',
'only screen and (min-width : 960px)' //media type
);
/* *keep reading* */
}
add_action('init', 'mytheme_register_styles');
We have used CSS3 media queries to prevent mobile browsers from parsing our desktop style sheet. But Internet Explorer versions 8 and below do not understand CSS3 media queries and so will not parse the desktop CSS either.
IE8 is only two years old, so we should support its users with conditional comments.
Conditional Comments
When registering CSS using the register and enqueue functions, conditional comments are a little more complex. WordPress uses the object $wp_styles to store registered style sheets.
To wrap your file in conditional comments, add extra information to this object.
For Internet Explorer 8 and below, excluding mobile IE, we need to register another copy of our desktop style sheet (using the media type all) and wrap it in conditional comments.
In the code sample above, /* *keep reading* */ would be replaced with the following:
global $wp_styles;
wp_register_style(
'theme-desktop-ie',
'/wp-content/themes/my-theme/desktop.css',
array('theme-mobile'),
'1.0.0'
);
$wp_styles->add_data(
'theme-desktop-ie', //handle
'conditional', //is a conditional comment
'!(IEMobile)&(lte IE 8)' //the conditional comment
);
Unfortunately, there is no equivalent for wrapping JavaScript files in conditional comments, presumably due to the concatenation of JavaScript in the admin section.
If you need to wrap a JavaScript file in conditional comments, you will need to add it to header.php or footer.php in the theme. Alternatively, you could use the wp_head or wp_footer hooks.
Outputting The Style Sheet HTML
Outputting the style sheet HTML is very similar to outputting the JavaScript HTML. We use the enqueue function and run it on the wp_print_styles hook.
In our example, we could get away with telling WordPress to queue only the style sheets that have the handles theme-desktop and theme-desktop-ie. WordPress would then output the mobile/all media version.
However, both style sheets apply styles to the website beyond a basic reset: mobile.css builds the website for mobile phones, and desktop.css builds on top of that. If it does something and I’ve registered it, then I should enqueue it. It helps to keep track of what’s going on.
Here is the code to output the CSS to the HTML:
function mytheme_enqueue_styles(){
if (!is_admin()):
wp_enqueue_style('theme-mobile'); //mobile.css
wp_enqueue_style('theme-desktop'); //desktop.css
wp_enqueue_style('theme-desktop-ie'); //desktop.css lte ie8
endif; //!is_admin
}
add_action('wp_print_styles', 'mytheme_enqueue_styles');
What’s The Point?
You may be wondering what the point is of going through all of this extra effort when we could just output our JavaScript and style sheets in the theme’s header.php or using the wp_head hook.
In the case of CSS in a standalone theme, it’s a valid point. It’s extra work without much of a payoff.
But with JavaScript, it helps to prevent clashes between plugins and themes when each uses a different version of a JavaScript framework. It also makes page-loading times as fast as possible by avoiding file duplication.
WordPress Frameworks
This group of functions can be most helpful when using a framework for theming. In my agency, Soupgiant, we’ve built a framework to speed up our production of websites.
As with most agencies, we have internal conventions for naming JavaScript and CSS files.
When we create a bespoke WordPress theme for a client, we develop it as a child theme of our framework. In the framework itself, we register a number of JavaScript and CSS files in accordance with our naming convention.
In the child theme, we then simply enqueue files to output the HTML.
function clienttheme_enqueue_css() {
if (!is_admin()):
wp_enqueue_style('theme-mobile');
wp_enqueue_style('theme-desktop');
wp_enqueue_style('theme-desktop-ie');
endif; //!is_admin
}
add_action('wp_print_styles', 'clienttheme_enqueue_css');
function clienttheme_enqueue_js() {
if (!is_admin()):
wp_enqueue_script('theme-custom');
endif; //!is_admin
}
add_action('wp_print_scripts', 'clienttheme_enqueue_js');
Adding CSS and JavaScript to our themes the WordPress way enables us to keep track of exactly what’s going on at a glance.
A Slight Limitation
If you use a JavaScript framework in your theme or plugin, then you’re stuck with the version that ships with the current version of WordPress, which sometimes falls a version or two behind the latest official release of the framework. (Upgrading to a newer version of the framework is technically possible, but this could cause problems with other themes or plugins that expect the version that ships with WordPress, so I’ve omitted this information from this article.)
While this prevents you from using any new features of the framework that were added after the version included in WordPress, the advantage is that all theme and plugin authors know which version of the framework to expect.
A Single Point Of Registration
Register your styles and scripts in a single block of code, so that when you update a file, you will be able to go back and update the version number easily.
If you use different code in different parts of the website, you can wrap the logic around the enqueue scripts.
If, say, your archive pages use different JavaScript than the rest of the website, then you might register three files:
- base JavaScript (registered as
theme-base), - archive JavaScript (registered as
theme-archive), - general JavaScript (registered as
theme-general).
Again, the base JavaScript adds nothing to the website. Rather, it is a group of default functions that the other two files rely on. You could then enqueue the files using the following code:
function mytheme_enqueue_js(){
if (is_archive()) {
wp_enqueue_script('theme-archive');
}
elseif (!is_admin()) {
wp_enqueue_script('theme-general');
}
}
add_action('wp_print_scripts', 'mytheme_enqueue_js');
Using The Google AJAX CDN
While using JavaScript the WordPress way will save you the problem of common libraries conflicting with each other, you might prefer to serve these libraries from Google’s server rather than your own.
Using Jason Penny’s Use Google Libraries plugin is the easiest way to do this. The plugin automatically keeps jQuery in noConflict mode.
Putting It All Together
Once you’ve started registering and outputting your scripts and styles the WordPress way, you will find that managing these files becomes a series of logical steps:
- Registration to manage:
- version numbers,
- file dependencies,
- media types for CSS,
- code placement for JavaScript (header or footer);
- Enqueue/output files to HTML:
- logic targeting output to specific WordPress pages,
- WordPress automating dependencies.
Eliminating potential JavaScript conflicts from your WordPress theme or plugin frees you to get on with more important things, such as following up on sales leads or getting back to that hash-tag game that was so rudely interrupted.
(al)


Leon
October 12th, 2011 7:51 amThanks for this info—finding this level of detail has been difficult for me.
I need to be able to add conditional javascript to my theme the ‘proper’ way for it to get approval from the theme directory. Just sticking the conditional comments in
header.phpmeans it won’t get through.I’ve tried using
wp_headbut found it simply doesn’t work.Looks like it’s not possible—but that’s good to know.
Peter Wilson
October 12th, 2011 3:19 pmI do it using code similar to this https://gist.github.com/1282923
Slind
October 13th, 2011 11:11 amHey Peter,
I know this is not the topic.
But can you tell why the googlebot inst indexing my picture galleries, or how i can fix this?
j-lind.de
Gabriele Romanato
October 12th, 2011 8:27 amMost developers simply ignore the fact that they can use self-executing functions to create a new namespace inside their application. So (function($) {…})(jQuery) operates on jQuery, but you can use the same principle to include your library code: (function() { var MyLib = {};)(); It is safe to use jQuery within that context, because it’s like a sandbox.
Another thing to keep in mind is the order by which jQuery plugins are executed: generally, they all use the ready() event, so you may have multiple ready() calls. You can tackle this by creating an autoload method and wrap the plugin calls within the methods of your library:
var MyApp = new function() {
this.twitterPlugin = function() {
…
};
// other plugin calls
this.autoload = function() {
for(var i in this) {
if(typeof this[i] === ‘function’ && this[i] !== arguments.callee) {
this[i]();
}
}
};
}();
Then you’ll have a single call:
$(function() {
MyApp.autoload();
});
Generally is better to include all the JavaScript code at the end of the page for a better perceived performance (see Steve Souders, Yahoo! team), but there may be some plugins that need a different source placement.
Another thing to keep in mind, if you use web fonts, is that your include CSS must come before the CSS that uses it. This is the case of Google Web Fonts. Also consider the fact that this kind of CSS may actually negatively affect the performance of your site if the requested font is not available. Browsers, in this case, tend to freeze and slow down the rendering of the page.
das
October 12th, 2011 8:38 am“wordpress for developers” should be existing. imagine that. (without the unnecessary comfort functions it would be a way better cms.)
Sayontan
October 12th, 2011 9:30 amThere are problems using add_data for negative conditionals (see http://core.trac.wordpress.org/ticket/16118). Instead you can use the style_loader_tag filter:
add_filter(‘style_loader_tag’, ‘custom_css_filter’, 10, 2);
function custom_css_filter($css_html_tag, $handle) {
if ($handle == ‘whatever-handle-you-use’) {
return “<!–[if !IE]>–>”.$css_html_tag.”<!–<![endif]–><!–[if gt IE 8]>”.$css_html_tag.”<![endif]–>”;
}
return $css_html_tag;
}
Edouard Duplessis
October 12th, 2011 10:06 ama better hook to use is “template_redirect” for loading your js or css
1 it’s loading only in front end… so no ” if(!is_admin()) ”
2 You know which template file is loading so if you need a conditionnal loading you have it.
if(is_home()){
wp_enqueue_style(‘home’);
}else{
wp_enqueue_style(‘page’);
}
and if you use a parent theme for development
register your style or script in “after_setup_theme” hook in your parent theme
and in your child register it in “after_setup_theme” but in level 12, so it register after your parent theme.
And for a WordPress for developers, read the book “Professional WordPress Plugin Development” by Brad Williams, Ozh Richard, Justin Tadlock
Ken
October 12th, 2011 10:19 amwhy not use
jQuery(document).ready(function($) {
// $() will work as an alias for jQuery() inside of this function
});
or
(function($) {
// $() will work as an alias for jQuery() inside of this function
})(jQuery);
for the alias enabling?
Emil
October 12th, 2011 1:35 pmI’ve had so many conflicts with jQuery so this article is really worth a lot to me!
Thanks bro!
Nico
October 13th, 2011 12:04 amQuite long article for the 4 functions you need for that :D
But ofcourse usefull for beginners
jimmy
October 13th, 2011 6:43 amGreat insight! How do we insert location into the boolean search string?
Edwin Kwan
October 18th, 2011 2:17 pmI’m not really getting how registering your javascript and css will prevent conflicts. There’s still the potential for conflicting javascripts and css as it doesn’t stop a plugin for registering their own copy of jquery and have a second plugin use wordpress’ jquery and you’re back to the same problem?
wp_register_script( “a-different-version-of-jquery”, … );
wp_enqueue_script(‘a-different-version-of-jquery’);
Am I missing something?
Peter Wilson
October 18th, 2011 2:39 pmThat’s true, it only works if all your plugins register & enqueue JavaScript the WordPress way. I wish to encourage all authors to do so.
If a plugin uses its own version of a jQuery library could be seen as a warning to review its code.
Duncan
October 19th, 2011 2:05 amWhat would be the best why to add a chuck of code in the head of the site. I’m registering the main script the way you described above but would like to know the correct way of adding something like the example below:
function function_name() {
echo ”
jQuery(document).ready(function(){
jQuery(‘ul.sf-menu’)
.supersubs()
.superfish ({
delay:500,
animation:{opacity:’show’,height:’show’},
speed:’normal’,
dropShadows:true
});
});
“;
}
add_action(‘wp_head’, ‘function_name’, 9);
Peter Wilson
October 20th, 2011 6:45 pmThat would do the trick with some html script tags in output.
You would be better off putting it in the site’s main JavaScript file rather than outputting it in the HTML. If you must put it in the HTML, attach the function to the wp_footer hook – instead of wp_head – your jQuery doesn’t run until the DOM has fully loaded.
Chris Raymond
November 4th, 2011 12:30 pmThis one caught me. All the Wizylab Premium themes seem to have created their own wizy_functionname including to call jquery. So now my blog loads jquery twice. Since I am not a php coder I have not been able to figure out how to modify the Wizylab Gridnik theme to properly enqueue and register scripts, though I did at least get it to load the same version of jquery as what comes with WP.
Tominari
May 24th, 2012 8:12 pmWe need a lot more inghsits like this!
saurabh
July 12th, 2012 7:29 amEn queuing the mobile.css (using the function mytheme_enqueue_styles()) was’nt necessary as it will get automatically loaded bcoz it is required the desktop.css style sheet just as in the previous example we did not enquqe the jquery…
livesmart360
July 19th, 2012 3:43 amThis article is excellent and very useful!!