Asynchronously load link-tag stylesheets with promise result indicating load completion
MIT License
Asynchronously load link-tag stylesheets with promise result indicating load completion. May also be used for favicon-loading.
The advantage over injecting into <style>
after fetch
is that with
<link>
injection, one gets separate stylesheet documents which don't
clutter the source and which can be viewed as separate documents in
the web console. Loading also appears to occur more quickly.
Useful for code libraries which allowing for parallel loading of stylesheets (including optionally user-supplied one(s)) related to that widget/library but in a modular manner (akin to ES6 Modules but for stylesheets). No need for your main HTML to specify the stylesheets the widget is using internally.
npm i load-stylesheets
or:
yarn add load-stylesheets
<script src="node_modules/load-stylesheets/dist/index-umd.cjs"></script>
The global will be loadStylesheets
.
or, using ES6 modules:
import loadStylesheets from './node_modules/load-stylesheets/dist/index-es.js';
<Promise> promise = loadStylesheets(<string|Array of strings and/or two-item arrays of path and options> paths, <object> options?);
loadStylesheets
options<link>
will be added. Choose this or before
or the default which<head>
.<link>
will be added. Choose this or after
or the default which<head>
.load
events for favicon linkstrue
allows us to know when the imagefalse
, the separate loading as an image is<link>
is added to the page regardless of whether it has loadedimage
is set to true
data:
URL.false
, the image loading will merely serve to detect the point<link>
href
data:
URL.error
, stylesheetURL
, options
, resolve
, reject
. Theconst stylesheetElements = await loadStylesheets([
'path/to/styles.css',
'a/different/path/to/styles.css'
]);
const stylesheetElements = await loadStylesheets([
'path/to/styles.css',
['path/to/favicon.png', {favicon: true, before: document.head}],
'a/different/path/to/styles.css'
], {before: document.body.lastElementChild});
For example, a code library might use load-stylesheets
internally
to allow for an API such as:
// main.js
import Widget from './widget.js';
// We even do the title in JavaScript
document.title = 'Internationalizable title';
const widget = await new Widget({
stylesheets: ['@builtin', '/path/to/custom/styles.css']
}).init();
// the stylesheets were loaded and then the widget added
// widget.js
import loadStylesheets from 'load-stylesheets';
class Widget {
constructor ({stylesheets}) {
// We'll allow control in one place of whether the user wants the
// built-in stylesheets for this widget or not
this.stylesheets = stylesheets.map((s) => {
return s === '@builtin' ? '/path/to/widget.css' : s;
});
}
async init () {
this._stylesheetElements = await loadStylesheets(this.stylesheets);
// The stylesheets have now been loaded, so your widget will be
// added without "jankiness" and without need for your users to
// non-modularly add stylesheets to their main HTML
// Begin widget-building code here
return this; // Return `Widget` instance for convenience
}
}
export default Widget;
After building the ES6 modules (e.g., using Rollup), your HTML will then be as clean as:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
</head>
<body>
<script type="module" src="dist/main.js"></script>
</body>
</html>
<style>
tags (and also <script>
)