Enqueued Style Sheet Extras Fine-tuning your additional style sheets

The WP_Styles class in WordPress allows for a few extra bits of fine-tuning via the extra property, which is amended by calling add_data( $handle, $key, $value ) method on the global $wp_styles.


Persistent, Preferred and Alternate Style Sheets

Back at the end of 1999, the HTML4 spec defined persistent, preferred and alternate style sheets, and several of the browsers at the time implemented a user interface for users to access these as they wanted.

Several better concepts came along, such as sites doing on-site front-end or back-end style switchers, which solved some of the issues such as persistence on page reloads, supporting browsers which didn’t yet support a user interface, and avoiding downloading multiple style sheets that a user may never actually select.

Persistent style sheets are always loaded by the browser, and the link element does not have a title attribute. The Preferred (default) alternate style sheet has a title attribute, and the other alternate style sheets also have alternate as one of the rel attribute values.

However, the technique is still valid today, and can be implemented when enqueueing style sheets in WordPress. Here’s how you might add a couple of alternative style sheets (with one marked as the default alternative, or preferred) for instance:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
<?php
add_action( 'wp_enqueue_scripts', 'child_add_alternate_style_sheet' );
/**
* Enqueue preferred and alternate style sheet.
*
* WordPress already adds a persistent style sheet (style.css), so this
* function gives examples of adding a preferred and alternative style sheets.
*
* Persistent = browser MUST apply it.
* Preferred = browser SHOULD apply it, unless user has selected a different alternative.
* Alternative = browser should allow users to select from these mutually exclusive style sheets.
*
* @author Gary Jones
* @link http://code.garyjones.co.uk/enqueued-style-sheet-extras/
* @see http://www.w3.org/TR/html4/present/styles.html#h-14.3.1
*/
function child_add_alternate_style_sheet() {
global $wp_styles;
// Add a prefered style sheet, for the normal contrast (colours, font sizes etc)
wp_enqueue_style( 'child-default', get_stylesheet_directory_uri() . '/style-default.css', array(), '1.0' );
$wp_styles->add_data( 'child-default', 'title', __( 'Default', 'child-theme-textdomain' ) );
// Add an alternative style sheet, high contrast.
wp_enqueue_style( 'child-highcontrast', get_stylesheet_directory_uri() . '/style-highcontrast.css', array(), '1.0' );
$wp_styles->add_data( 'child-highcontrast', 'title', __( 'High Contrast', 'child-theme-textdomain' ) );
$wp_styles->add_data( 'child-highcontrast', 'alt', true );
}
view raw functions.php hosted with ❤ by GitHub

On Firefox for instance, a user can pick between these style sheets via the View -> Page Styles menu item:

Screenshot showing selecting between preferred and alternate style sheets in Firefox

Selecting between preferred and alternate style sheets in Firefox

Internet Explorer Style Sheets

Another extra is the ability to set a conditional comment, as used for adding IE-specific style sheets. Previously it had to be done by enqueueing the style sheet for all browsers, and then filtering the style_loader_tag for that handle and adding the conditional comments in around it. Now we can just do:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<?php
add_action( 'wp_enqueue_scripts', 'prefix_add_ie8_style_sheet', 200 );
/**
* Enqueue a IE-specific style sheet.
*
* Add a style sheet for everyone, then mark it as conditional to IE8 or below.
*
* @author Gary Jones
* @link http://code.garyjones.co.uk/enqueued-style-sheet-extras/
*/
function prefix_add_ie8_style_sheet() {
global $wp_styles;
wp_enqueue_style( 'child-ie8', get_stylesheet_directory_uri() . '/style-ie8.css', array(), '1.0.0' );
$wp_styles->add_data( 'child-ie8', 'conditional', 'lte IE 8' );
}
view raw functions.php hosted with ❤ by GitHub

This has the advantage of being significantly less code, and the actual condition could come from a variable or be filterable.

Other Extras

WordPress also appears to support other extras, such as rtl which would allow you to mark an enqueued style sheet as only being referenced if the site was set to use a right-to-left language (the best practice is to create a style sheet called rtl.css which does this automatically). Other extras include suffix and after although these are used more by WordPress internally for setting the reference to a minified / non-minified file, and for setting internal style sheet data to appear after a specific external style sheet reference via wp_add_inline_style().

Since the name of the extra key is not fixed, you could add some of your own arbitrary meta data to associate with an enqueued style sheet (remember to prefix the key so you avoid any potential clashes with WordPress-supported keys in the future).

Comments

  1. Hello Gary,
    thanks for this post. I have used your info to use IE-specific style sheets (IE 7,8 & 9) and it works well.
    I built this site as a newcomer, and am not able to write code, but can understand (mostly) what it does.

    I have separate for (IE 7,8 & 9), and repeat the above code for each, with the necessary changes for each.
    Is it possible to combine the 3 statements into one to remove the duplication? If so, would you mind helping with this?
    Thanks
    M

    • Hi Mark,

      Can you post your code somewhere (Gist, pastebin etc.) so I can see what exactly it is you’ve already got?

  2. paul says:

    hey there is

    there anyway I could do something similar for scripts ? I want to use the register function to make sure no one else has loaded the IE fallback script I’m using for canvas support and then enqueue it but only want it happen in IE8 and below. This script only need to run in IE8 and below so seems reasonalbe to me to use an IE conditional over feature detection from inside my plugin. Any thoughts ?

    • Conditional comments for scripts are unfortunately not support yet in WP core. There is a ticket for it, but as the world moves away from oldIE, then there’s less emphasis to add it in.
      Instead of using conditional comments to target a browser, or browser-sniffing, the accepted way of adding fallback is via feature-detection – that is, you use JS to check to see if canvas is supported in whatever browser is being used, and if not, then the fallback kicks in. You may like to look at Modernizr and similar feature-detection scripts.

  3. paul says:

    Hi Gary thanks for the response.

    I’m very familiar with the concept of feature detection and have been using moderninzr for quite a while but I feel like its over kill in a situation where I’m ONLY providing a polyfill for oldIE. but I’ll just continue to jam to conditionals into the head via a hook, would have been nice to have it only register and enqueue for IE, so that my plugin doesn’t duplicate stuff, but then again I don’t feel that bad about punishing old IE users.

  4. Gary, this IE code was a lifesaver for me today! I did not realize that Genesis 2.0 (sample) does nothing friendly for IE8 (other than one img declaration) and had to put something together in a hurry to make a new site work in it. Being able to conditionally load an IE8 stylesheet really helped–I was able to change a minimum of code and I seem to be OK even there. I don’t like IE any better but at least the people using it won’t be wondering what on earth I was thinking.

Trackbacks

  1. […] like to thank Gary Jones for his general awesomeness, but specifically today for his easy method to get some IE8 (and lower) love going on for your […]

Speak Your Mind

*