简体   繁体   English

Javascript:我可以动态创建一个 CSSStyleSheet 对象并插入它吗?

[英]Javascript: Can i dynamically create a CSSStyleSheet object and insert it?

I know document.styleSheets which consists of all valid style sheets in a page.我知道document.styleSheets由页面中的所有有效样式表组成。 I want to know whether i can create a new one and append it to present list via javascript.我想知道我是否可以创建一个新的并通过 javascript 将其附加到当前列表中。

I have tried document.styleSheets[0].constructor , document.styleSheets[0].__proto__.constructor , new CSSStyleSheet , CSSStyleSheet() , all what i get from Chrome is TypeError: Illegal constructor .我试过document.styleSheets[0].constructor , document.styleSheets[0].__proto__.constructor , new CSSStyleSheet , CSSStyleSheet() ,我从 Chrome 得到的都是TypeError: Illegal constructor CSSStyleSheet.constructor() returned a pure object but i expect a CSSStyleSheet object. CSSStyleSheet.constructor()返回一个纯对象,但我期望一个 CSSStyleSheet 对象。

I know i can create a link/style element and append it, then modify it.我知道我可以创建一个链接/样式元素并附加它,然后修改它。 What i want to know is that, can i create such object directly with javascript?我想知道的是,我可以直接用 javascript 创建这样的对象吗?

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 :一些人在上面详细介绍了这种方法,但我注意到没有人掩盖HTMLStyleElementHTMLLinkElement都有一个整洁的sheet属性来直接访问它们的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比通过document.styleSheets搜索要简单得多

There's a brand new proposal that makes it possible to directly call the CSSStyleSheet constructor.一个全新的提议可以直接调用CSSStyleSheet构造函数。 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];

Note that currently this only works on Chrome Canary, but hopefully other browsers will implement this feature soon.请注意,目前这仅适用于 Chrome Canary,但希望其他浏览器能尽快实现此功能。

If you are trying to write the css inside of javascript, do this:如果您尝试在 javascript 中编写 css,请执行以下操作:

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);

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: document.styleSheets不能直接修改,但是你可以通过给你的文档添加一个新的样式标签来添加一个条目:

// 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 .如果您运行 Firefox,您可以直接在 Scratchpad 中进行测试:复制代码,按Shift+F4 ,粘贴它,然后使用Ctrl+L运行代码。 Have fun!玩得开心!

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 ).据我所知,唯一接近您要求的方法是IE-only document.createStyleSheet([url] [,index])方法,您可以使用该方法创建最多 31 * styleSheet对象(之后您仍然需要手动创建style元素并将它们附加到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 浏览器定义createStyleSheet()方法,但正如您所期望的那样,它通过附加link / style元素(出于某种原因您试图避免)来实现。


* IE 6 to 9 is limited to 31 imported stylesheets due to 5-bit field used for storing sheet IDs . * 由于用于存储工作表 ID 的 5 位字段, IE 6 到 9 仅限于 31 个导入的样式表。 In IE10 this limit has been raised to 4095.在 IE10 中,此限制已提高到 4095。

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.假设 document.styleSheets[0] 是一个 CSSStyleSheet 对象,实际上如果您将 document.styleSheets[0] 替换为任何 CSSStyleSheet 它将起作用。

Object.create(CSSStyleSheet.prototype)

gives you back an empty instance of CSSStyleSheet.返回一个空的 CSSStyleSheet 实例。 In other words, it does exactly what you would expect new CSSStyleSheet to do.换句话说,它所做的正是您期望new CSSStyleSheet所做的。

Object.create is available in any browser with ECMAScript 5 support. Object.create可在任何支持 ECMAScript 5 的浏览器中使用。 Find a compatibility table here .在此处查找兼容性表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM