Reputation: 1174
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?
Upvotes: 33
Views: 23904
Reputation: 271
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];
Upvotes: 27
Reputation: 1
Safari support CSSStyleSheet since 16.4 : https://developer.apple.com/documentation/safari-release-notes/safari-16_4-release-notes#CSS-API
Upvotes: 0
Reputation: 4264
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!
Upvotes: 5
Reputation: 6554
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);
Upvotes: 7
Reputation: 5308
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
Upvotes: 22
Reputation: 3646
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.
Upvotes: 2
Reputation: 577
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.
Upvotes: 2
Reputation: 86934
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.
Upvotes: 4