Skip to content
This repository was archived by the owner on Oct 21, 2022. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: filamentgroup/loadCSS
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.2.1
Choose a base ref
...
head repository: filamentgroup/loadCSS
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Loading
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
dist
9 changes: 8 additions & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
@@ -12,5 +12,12 @@
"unused": true,
"node": true,
"loopfunc": true,
"predef": [ "window", "document", "define", "shoestring", "XMLHttpRequest", "ActiveXObject", "Window", "localStorage" ]

"browser": true,
"qunit": true,

"globals": {
"loadCSS": false,
"onloadCSS": false
}
}
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
1 change: 0 additions & 1 deletion .repo-rt

This file was deleted.

2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: node_js
node_js:
- '0.11'
- 12.6.0
before_script:
- npm install
script: grunt -v
40 changes: 32 additions & 8 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,47 @@
/* global module:false */
module.exports = function(grunt) {

// Project configuration.
require( 'matchdep' ).filterDev( ['grunt-*', '!grunt-cli'] ).forEach( grunt.loadNpmTasks );

// Project configuration.
grunt.initConfig({
jshint: {
jshint: {
all: {
options: {
jshintrc: ".jshintrc"
},

src: ['Gruntfile.js', '*.js']
src: [
'*.js',
'test/**/*.js',
'src/**/*.js',
]
}
},
concat: {
dist: {
files: {
'dist/loadCSS.js': ['src/loadCSS.js'],
'dist/onloadCSS.js': ['src/onloadCSS.js']
}
}
},
uglify: {
options: {
preserveComments: /^\!/
},
dist: {
files: {
'dist/loadCSS.min.js': ['src/loadCSS.js'],
'dist/onloadCSS.min.js': ['src/onloadCSS.js']
}
}
},
qunit: {
qunit: {
files: ['test/qunit/**/*.html']
}
});
});

grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.registerTask('default', ['jshint', 'qunit']);
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
grunt.registerTask('stage', ['default']);
};
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Filament Group
Copyright (c) @scottjehl, 2016 Filament Group

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
184 changes: 55 additions & 129 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,165 +1,91 @@
:warning: This project is archived and the repository is no longer maintained.

# loadCSS

A function for loading CSS asynchronously
[c]2015 @scottjehl, Filament Group, Inc.
A pattern for loading CSS asynchronously
[c]2020 @scottjehl, @zachleat [Filament Group, Inc.](https://www.filamentgroup.com/)
Licensed MIT

## Usage
## Why an ansychronous CSS loader?

Place the [`loadCSS` function](https://github.com/filamentgroup/loadCSS/blob/master/loadCSS.js) inline in the `head` of your page (it can also be included in an external JavaScript file if preferable).
Referencing CSS stylesheets with `link[rel=stylesheet]` or `@import` causes browsers to delay page rendering while a stylesheet loads. When loading stylesheets that are not critical to the initial rendering of a page, this blocking behavior is undesirable. The pattern below allows us to fetch and apply CSS asynchronously. If necessary, this repo also offers a separate (and optional) JavaScript function for loading stylesheets dynamically.

Then call it by passing it a stylesheet URL:

``` html
<head>
...
<script>
// include loadCSS here...
function loadCSS( href, before, media ){ ... }
// load a file
loadCSS( "path/to/mystylesheet.css" );
</script>
<noscript><link href="path/to/mystylesheet.css" rel="stylesheet"></noscript>
...
</head>
## How to use

As a primary pattern, we recommend loading asynchronous CSS like this from HTML:

`<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'; this.onload=null;">`

This article explains why this approach is best: https://www.filamentgroup.com/lab/load-css-simpler/

That is probably all you need! But if you want to load a CSS file from a JavaScript function, read on...

## Dynamic CSS loading with the loadCSS function

The [loadCSS.js](https://github.com/filamentgroup/loadCSS/blob/master/src/loadCSS.js) file exposes a global `loadCSS` function that you can call to load CSS files programmatically, if needed. This is handy for cases where you need to dynamically load CSS from script.

``` javascript
loadCSS( "path/to/mystylesheet.css" );
```

By default, loadCSS will inject the new CSS stylesheet *after* the last stylesheet or script in the page. This should retain your CSS cascade as you'd expect.
The code above will insert a new CSS stylesheet `link` *after* the last stylesheet or script that it finds in the page, and the function will return a reference to that `link` element, should you want to reference it later in your script. Multiple calls to loadCSS will reference CSS files in the order they are called, but keep in mind that they may finish loading in a different order than they were called.

## Function API

The loadCSS function has 3 optional arguments.

#### Optional Arguments
- `before`: By default, loadCSS attempts to inject the stylesheet link *after* all CSS and JS in the page. However, if you desire a more specific location in your document, such as before a particular stylesheet link, you can use the `before` argument to specify a particular element to use as an insertion point. Your stylesheet will be inserted *before* the element you specify. For example, here's how that can be done by simply applying an `id` attribute to your `script`.
``` html
```html
<head>
...
<script id="loadcss">
// include loadCSS here...
function loadCSS( href, before, media ){ ... }
// load a file
// load a CSS file just before the script element containing this code
loadCSS( "path/to/mystylesheet.css", document.getElementById("loadcss") );
</script>
<noscript><link href="path/to/mystylesheet.css" rel="stylesheet"></noscript>
...
</head>
```

- `media`: You can optionally pass a string to the media argument to set the `media=""` of the stylesheet - the default value is `all`.
- `attributes`: You can also optionally pass an Object of attribute name/attribute value pairs to set on the stylesheet. This can be used to specify Subresource Integrity attributes:
```javascript
loadCSS(
"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css",
null,
null,
{
"crossorigin": "anonymous",
"integrity": "sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
}
);
```

#### Using with `onload`

Onload listener support with `link` elements is spotty, so if you need to add an onload callback, include [`onloadCSS` function](https://github.com/filamentgroup/loadCSS/blob/master/onloadCSS.js) on your page and use the `onloadCSS` function:
``` javascript
function onloadCSS( ss, callback ){ ... }
Onload event support for `link` elements is spotty in some browsers, so if you need to add an onload callback, include [`onloadCSS` function](https://github.com/filamentgroup/loadCSS/blob/master/src/onloadCSS.js) on your page and use the `onloadCSS` function:

```javascript
var stylesheet = loadCSS( "path/to/mystylesheet.css" );
onloadCSS( stylesheet, function() {
console.log( "Stylesheet has asynchronously loaded." );
console.log( "Stylesheet has loaded." );
});
```

### Browser Support

LoadCSS attempts to load a css file asynchronously, while maintaining the CSS cascade, in any JavaScript-capable browser. However, some older browsers will block rendering while the stylesheet is loading. This table outlines css loading support and async loading support.

<table>
<tr>
<th>Browser</th>
<th>CSS Loads Successfully</th>
<th>CSS Loads without Blocking Render</th>
</tr>
<tr>
<th>Chrome Mac (latest and many recent versions)</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Firefox Desktop (latest and many recent versions)</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Opera Mac (latest and many recent versions)</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Safari Mac (latest and many recent versions)</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Safari iOS (latest and many recent versions)</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Chrome Android 5.x</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Chrome Android 4.x</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Android Browser 2.3</th>
<th>Yes</th>
<th>No</th>
</tr>
<tr>
<th>Kindle Fire HD</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>Windows Phone IE 8.1</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>IE 11</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>IE 10</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>IE 9</th>
<th>Yes</th>
<th>Yes</th>
</tr>
<tr>
<th>IE 8</th>
<th>Yes</th>
<th>No</th>
</tr>
<tr>
<th>IE 7</th>
<th>Yes</th>
<th>No</th>
</tr>
<tr>
<th>IE 6</th>
<th>Yes</th>
<th>No</th>
</tr>

</table>



### Usage Tips

We typically use `loadCSS` to load CSS files that are non-critical to the initial rendering of a site. See the [EnhanceJS project Readme](https://github.com/filamentgroup/enhance#enhancejs) for examples of how we typically use it to improve page loading performance.

The reason this script is sometimes necessary is because there is no cross-browser means in HTML (currently at least) to load and apply a CSS file asynchronously. CSS references that use either `link` or `import` will cause browsers to block page rendering by default while their related stylesheet loads.
The loadCSS patterns attempt to load a css file asynchronously in any JavaScript-capable browser. However, some older browsers such as Internet Explorer 8 and older will block rendering while the stylesheet is loading. This merely means that the stylesheet will load as if you referenced it with an ordinary link element.

#### Contributions and bug fixes

Both are very much appreciated - especially bug fixes. As for contributions, the goals of this project are to keep things very simple and utilitarian, so if we don't accept a feature addition, it's not necessarily because it's a bad idea. It just may not meet the goals of the project. Thanks!
# Changes in version 3.0 (no more preload polyfill)

As of version 3.0, we no longer support or include a polyfill for a `rel=preload` markup pattern. This is because we have since determined that the markup pattern described at the top of this readme is simpler and better for performance, while the former preload pattern could sometimes conflict with resource priorities in ways that aren't helpful for loading CSS in a non-blocking way.

To update, you can change your preload markup to [this HTML pattern](https://github.com/filamentgroup/loadCSS/blob/master/README.md#how-to-use) and delete the JS from your build.

Since this change breaks the API from prior versions, we made it a major version bump. That way, if you are still needing to use the now-deprecated preload pattern, you can keep your code pointing at prior versions that are still on NPM, such as version 2.1.0 https://github.com/filamentgroup/loadCSS/releases/tag/v2.1.0


#### Contributions and bug fixes

Both are very much appreciated - especially bug fixes. As for contributions, the goals of this project are to keep things very simple and utilitarian, so if we don't accept a feature addition, it's not necessarily because it's a bad idea. It just may not meet the goals of the project. Thanks!
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "loadcss",
"main": [
"loadCSS.js"
"src/loadCSS.js"
],
"ignore": [
"**/.*"
28 changes: 0 additions & 28 deletions onloadCSS.js

This file was deleted.

Loading