48
$.getScript('ajax/test.js', function() {
  alert('Load was performed.');
});

.. like the above code which loads an external JS on request, is there something similar available to load an external CSS stylesheet when required?

Like for example when I use lightboxes (inline popups) on my site, I want to avoid loading lightbox JS and CSS files onload, unless requested by the user.

Thanks

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
eozzy
  • 66,048
  • 104
  • 272
  • 428

7 Answers7

70

Yup: if you create a <link> tag linking to a stylesheet and add it to the <head> tag, the browser will load that stylesheet.

E.g.

$('head').append('<link rel="stylesheet" type="text/css" href="lightbox_stylesheet.css">');

However, as per @peteorpeter’s comments, this doesn’t work in IE 8 or under — there, you need to either:

  1. append the <link> before setting its href; or
  2. use IE’s document.createStyleSheet() method

Also, checking whether a link has already been added doesn’t work reliably across all browsers.

I would also question part of your premise:

I want to avoid loading lightbox JS and CSS files onload, unless requested by the user.

Why? To reduce page weight? I can understand the desire, but you should measure the size of your CSS and JS files (after minification and gzipping) with the lightbox code in there, and without, to see whether the reduction is worth:

  1. the added complexity of loading on-demand; and
  2. the slightly reduced responsiveness of the lightbox (because when loading on-demand, the lightbox will have to wait for its own CSS and JS to load before it can do its thing)

After minification and gzipping, there may well not be that much difference.

And bear in mind that you can instruct the browser to cache your CSS and JS for a long time, meaning it only gets downloaded when a user visits your site with an empty cache.

Community
  • 1
  • 1
Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
  • 4
    Yes it will load the stylesheet, but you shouldn't wrap your `link` statement in `$()` just use `lightbox_stylesheet = ''` and the `.append()` call will do what is needed. You generally don't want to wrap anything in a jQuery object that cannot be contained in a `div`. – Doug Neiner Jan 24 '10 at 07:08
  • Also, kudos for using a string of HTML vs. the separate `attr` calls. This will be faster (ok, just a smidge) than the separate calls. – Doug Neiner Jan 24 '10 at 07:12
  • Aha, I didn’t realise `append()` took a string of HTML too. Neat. – Paul D. Waite Jan 24 '10 at 08:16
  • 2
    Heads up: Checking to see if a `` has already been added by using `if('head link[href=foo]')` is not reliable [due to browser DOM limitations](http://stackoverflow.com/questions/6417157/jquery-selector-for-link-elements-in-head). – peteorpeter Mar 16 '12 at 10:37
  • 2
    Heads up 2: THIS WON'T WORK IN IE <= 8. See [this Q&A](http://stackoverflow.com/questions/1184950/dynamically-loading-css-stylesheet-doesnt-work-on-ie) – peteorpeter Mar 16 '12 at 10:50
  • I would add something like: if (!$("link[href='/path2/your.css']").length) before appending, or you may end up with many appended ... and some interesting problems – Jeffz Jun 30 '13 at 15:10
  • @Jeffz: ah sure, that could be a good idea. What problems would you see from attaching the same stylesheet twice though? if it’s the same stylesheet, surely attaching it once and attaching it ten times has the same effect (i.e. the styles therein are applied to the page)? – Paul D. Waite Jun 30 '13 at 15:14
  • @PaulD.Waite I worked with app where subpages opened in dialogs ... some of them dynamically sourced css ... at some point I noticed some 30 instances of same stylesheet appended to to main page. Not the best way to go. But that was "special case". – Jeffz Jun 30 '13 at 15:24
  • @Jeffz: sure. Did that cause any actual problems though? I guess it must have made e.g. the web inspector view a bit unusable (29 duplicate styles being overridden by the 30th for each element, oof). – Paul D. Waite Jun 30 '13 at 15:32
28
$('<link/>', {rel: 'stylesheet', href: 'myHref'}).appendTo('head');
Cody
  • 9,785
  • 4
  • 61
  • 46
12

You could do:

$('<link>').attr('rel','stylesheet')
  .attr('type','text/css')
  .attr('href','link_to.css')
  .appendTo('head');
Reigel Gallarde
  • 64,198
  • 21
  • 121
  • 139
  • 1
    @Reigel I am not sure how that would function cross browser. From my understanding, when you call `$(htmlString)` the element must be able to be contained in a `div` until it is appended to the page. Though a `link` element *can* be in a `div` it is not valid. For instance, you should not use `$(' – Doug Neiner Jan 24 '10 at 07:21
  • 1
    I think it’s a bit too obsessive to worry about where the HTML generated by JavaScript might be stored before it’s added to the page. The user’s never going to see that, right? – Paul D. Waite Jan 24 '10 at 08:19
  • 1
    @DougNeiner Youre wrong about that, 4 years later... what jQuery( expression ) does is return a set (array) of elements that match the the expression. The expression can be a selector or an html string. The elements are stored in memory as documentFragments and are passed by reference when you do something like var els = $(''); – qodeninja Feb 08 '14 at 02:12
5

You can add references to external stylesheets simply by adding dynamic HTML content in the head:

$('head').append('<link rel="stylesheet" href="style.css" type="text/css" />');

This content gets inserted in the DOM, and subsequently rendered normally, in this case causing a fetch of an external stylesheet.

Pay attention to cletus' answer as well however, as if you're not careful with dynamic loading of static content, it can end up costing you in page load time and excessive resource transfer.

zombat
  • 92,731
  • 24
  • 156
  • 164
2

Generally you're better off just including all you need assuming you're doing so correctly.

By that I mean that best practice for static content (images, Javascript, CSS) is to:

  • minimize external HTTP requests (minimize # of files);
  • version the files and use a far futures Expires header;
  • minify and compress content as appropriate.

so a user will only ever download a given file once until it changes.

Dynamically loading CSS and Javascript, unless it is exceptionally large, is typically unwarranted and counterproductive.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • 3
    There are times when it's necessary, however, for instance if you're writing a widget-style add-in, and you want to minimize how difficult it is to integrate it onto a given page. Being able to sell a "one-line integration" can be an important differentiator. – Ken Smith Nov 24 '12 at 09:22
2

IE issues...

I was crashing IE 6,7,8 with

$('head').append( $('<link rel="stylesheet" type="text/css" />').attr('href', 'assets/css/jquery.fancybox-1.3.4.css') );

Just copied them into the main sheet to avoid another http req, voila.

user541072
  • 21
  • 1
  • 1
    I just had the same problem (seems to be a 3 years old jquery bug) on IE7/8 and windows XP... Adding an empty href also circumvent the crash, e.g. $('').attr('href', 'assets/css/jquery.fancybox-1.3.4.css') – Shautieh Feb 16 '12 at 17:15
0

We can append it directly by

$("head").append($("<link rel='stylesheet' href='style.css' type='text/css' media='screen' />"));
subindas pm
  • 2,668
  • 25
  • 18