Skip to content

Commit 28d8144

Browse files
committed
Add insertInto option
Add another option - called `insertInto` - which allows specifying a CSS selector - e.g. `#styles` - to be used as an argument to `document.querySelector` to find an element into which to insert the generated `<style>`-tags. Will default to the `<head>`-tag if undefined.
1 parent 50af215 commit 28d8144

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ Note: Behavior is undefined when `unuse`/`unref` is called more often than `use`
4747

4848
### Options
4949

50+
#### `insertInto`
51+
By default, the style-loader inserts the `<style>` elements into the `<head>` tag of the page. If you want the tags to be inserted somewhere else, e.g. into a [ShadowRoot](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot), you can specify a CSS selector for that element here, e.g. `require('../style.css?insertInto=#host::shadow>#root')`.
52+
5053
#### `insertAt`
5154

52-
By default, the style-loader appends `<style>` elements to the end of the `<head>` tag of the page. This will cause CSS created by the loader to take priority over CSS already present in the document head. To insert style elements at the beginning of the head, set this query parameter to 'top', e.g. `require('../style.css?insertAt=top')`.
55+
By default, the style-loader appends `<style>` elements to the end of the style target, which is the `<head>` tag of the page unless specified by `insertInto`. This will cause CSS created by the loader to take priority over CSS already present in the target. To insert style elements at the beginning of the target, set this query parameter to 'top', e.g. `require('../style.css?insertAt=top')`.
5356

5457
#### `singleton`
5558

addStyles.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,18 @@ var stylesInDom = {},
1313
isOldIE = memoize(function() {
1414
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
1515
}),
16-
getHeadElement = memoize(function () {
17-
return document.head || document.getElementsByTagName("head")[0];
16+
getStyleTarget = (function(fn) {
17+
var memo = {};
18+
return function(selector) {
19+
if (typeof memo[selector] === "undefined") {
20+
console.log("FOO1memo", selector)
21+
memo[selector] = fn.call(this, selector);
22+
}
23+
console.log("FOO2memo", selector)
24+
return memo[selector]
25+
}
26+
})(function (styleTarget) {
27+
return document.querySelector(styleTarget)
1828
}),
1929
singletonElement = null,
2030
singletonCounter = 0,
@@ -30,7 +40,10 @@ module.exports = function(list, options) {
3040
// tags it will allow on a page
3141
if (typeof options.singleton === "undefined") options.singleton = isOldIE();
3242

33-
// By default, add <style> tags to the bottom of <head>.
43+
// By default, add <style> tags to the <head> element
44+
if (typeof options.insertInto === "undefined") options.insertInto = "head";
45+
46+
// By default, add <style> tags to the bottom of the target
3447
if (typeof options.insertAt === "undefined") options.insertAt = "bottom";
3548

3649
var styles = listToStyles(list);
@@ -100,19 +113,22 @@ function listToStyles(list) {
100113
}
101114

102115
function insertStyleElement(options, styleElement) {
103-
var head = getHeadElement();
116+
var styleTarget = getStyleTarget(options.insertInto)
117+
if (!styleTarget) {
118+
throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");
119+
}
104120
var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1];
105121
if (options.insertAt === "top") {
106122
if(!lastStyleElementInsertedAtTop) {
107-
head.insertBefore(styleElement, head.firstChild);
123+
styleTarget.insertBefore(styleElement, styleTarget.firstChild);
108124
} else if(lastStyleElementInsertedAtTop.nextSibling) {
109-
head.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
125+
styleTarget.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
110126
} else {
111-
head.appendChild(styleElement);
127+
styleTarget.appendChild(styleElement);
112128
}
113129
styleElementsInsertedAtTop.push(styleElement);
114130
} else if (options.insertAt === "bottom") {
115-
head.appendChild(styleElement);
131+
styleTarget.appendChild(styleElement);
116132
} else {
117133
throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
118134
}

0 commit comments

Comments
 (0)