33

I know document.styleSheets which consists of all valid style sheets in a page. I want to know whether I can create a new one and append it to present list via JavaScript.

I have tried document.styleSheets[0].constructor, document.styleSheets[0].__proto__.constructor, new CSSStyleSheet, CSSStyleSheet(), and all I get from Chrome is:

TypeError: Illegal constructor.

CSSStyleSheet.constructor() returned a pure object but I expect a CSSStyleSheet object.

I know I can create a link/style element and append it, then modify it. Can I create such objects directly with JavaScript?

TylerH
21.2k83 gold badges83 silver badges120 bronze badges
asked Nov 21, 2011 at 8:31
2
  • stackoverflow.com/questions/574944/… Commented Nov 21, 2011 at 8:34
  • 1
    simply create a new style element, and append it. a new CSSStyleSheet will be created. Commented Sep 11, 2012 at 5:04

8 Answers 8

27

There's a proposal that makes it possible to directly call the CSSStyleSheet constructor. Doing what you want to looks like this:

// Construct the CSSStyleSheet
const stylesheet = new CSSStyleSheet();
// Add some CSS
stylesheet.replaceSync('body { background: #000 !important; }')
// OR stylesheet.replace, which returns a Promise instead
// Tell the document to adopt your new stylesheet.
// Note that this also works with Shadow Roots.
document.adoptedStyleSheets = [stylesheet];
TylerH
21.2k83 gold badges83 silver badges120 bronze badges
answered Jan 12, 2019 at 18:27

Comments

22

I know you said you didn't want to create an element, but that's genuinely the only way to do it. A few people have detailed this approach above, but i notice nobody covered off that HTMLStyleElement and HTMLLinkElement both have a neat sheet property to get direct access to their CSSStyleSheet:

var style = document.createElement("style");
document.head.appendChild(style); // must append before you can access sheet property
var sheet = style.sheet;
console.log(sheet instanceof CSSStyleSheet);

Much simpler than searching through document.styleSheets

answered Jun 18, 2014 at 12:44

6 Comments

Additionally you may set the style.disabled property to true if you don't want to have a visual impact on your current document.
hi for me in chrome style.sheet isn't defined
@bluejayke I just pasted the exact snippet above into the chrome console and it worked. You can't access sheet property of stylesheets coming from another domain btw, the same-origin policy applies
@WickyNilliams Yes you're right... I was adding style.type = "style/css", which isn't even a valid type, when I took it out / changed it to "text/css", it worked :)
Note that you cannot edit this sheet using replace and friends, as its not a constructed StyleSheet.
|
7

If you are trying to write the css inside of javascript, do this:

var s = document.createElement('style');
s.type = 'text/css';
s.innerText = 'body { background: #222; } /*... more css ..*/';
document.head.appendChild(s);

Whereas if you are trying to load a stylesheet from the server:

var s = document.createElement('link');
s.type = 'text/css';
s.rel = 'stylesheet';
s.href = '/url/to/css/file.css';
document.head.appendChild(s);
user2683246
3,60832 silver badges31 bronze badges
answered Nov 21, 2011 at 8:41

3 Comments

Sorry, but i have said i know this method. I'm wondering whether i can create this object directly with javascript or not.
Don't use innerText, it's not part of any standard and doesn't have full browser compatibility. Use s.appendChild(document.createTextNode(styles)) for full compat.
@regality I want to create this object like new CSSStyleSheet, your method just pollutes DOM.
5

Yes, you can. The document.styleSheets cannot be modified directly, but you can add an entry by adding a new style tag to your document:

// Create the style element
var elem = $('<style id="lwuiStyle"></style>');
$('head').append(elem);
// Find its CSSStyleSheet entry in document.styleSheets
var yourSheet = null;
for (var sheet of document.styleSheets) {
 if (sheet.ownerNode == elem[0]) {
 yourSheet = sheet;
 break;
 }
}
// Test it by changing the background colour
yourSheet.insertRule('body {background-color: #fa0}', yourSheet.cssRules.length);

If you run Firefox, you can directly test this in Scratchpad: Copy the code, press Shift+F4, paste it, and run the code with Ctrl+L. Have fun!

answered Jul 2, 2013 at 10:18

Comments

4

As far as I know, the only approach that comes close to what you're asking for is the IE-only document.createStyleSheet([url] [,index]) method which you can use to create up to 31* styleSheet objects (after which you'll still need to manually create style elements and append them to document).

This answer shows how you can define the createStyleSheet() method for non-IE browsers but as you'd expect it does so by appending link/style elements (which for some reason you're trying to avoid).


* IE 6 to 9 is limited to 31 imported stylesheets due to 5-bit field used for storing sheet IDs. In IE10 this limit has been raised to 4095.

answered Nov 21, 2011 at 10:08

1 Comment

*Blink*. IE still continues to impress me.
2

Did you try this:

var myCSSStyleSheetIbj = Object.create(document.styleSheets[0])

Assuming that document.styleSheets[0] is a CSSStyleSheet Object, Actually if you replace document.styleSheets[0] with any CSSStyleSheet it would work.

answered Feb 5, 2013 at 15:15

2 Comments

To create an empty object, you might rather want to use Object.create(Object.getPrototypeOf(document.styleSheets[0])) here – but adding the object does not seem to be allowed.
Great, but once I create it, how do I insert it into my document?
2

Object.create(CSSStyleSheet.prototype)

gives you back an empty instance of CSSStyleSheet. In other words, it does exactly what you would expect new CSSStyleSheet to do.

Object.create is available in any browser with ECMAScript 5 support. Find a compatibility table here.

answered Feb 17, 2014 at 0:18

4 Comments

Perhaps you can elaborate? Instead of posting one line of rather cryptic code?
It's the answer to the question and so any comment would have been unnecessary in my eyes. The statement returns a new instance of CSSStyleSheet and that's it.
Great, now I have a new object, how do I insert it into my document?
While this looks like a good Idea, the resulting object is not usable as expected and throws an error - at least in Chrome and Firefox.
0

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.