Cssrules/Rules Are Null in Chrome

CSSRules is empty

I found these errors in your script:

  1. You're testing for type being equal to window.CSSRule.WEBKIT_KEYFRAMES_RULE. That property has a value of 8, whereas the desired object has a type of 1. A quick look in the CSSRule object reveals that you probably want to compare with window.CSSRule.STYLE_RULE.

  2. I couldn't find a property name, but in the end found a property selectorText containing #poulet.

After corrections the script reads:

function findKeyframesRule(rule)
{
var ss = document.styleSheets;

for (var i = 0; i < ss.length; ++i)
{
for (var j = 0; j < ss[i].cssRules.length; ++j)
{
if (ss[i].cssRules[j].type == window.CSSRule.STYLE_RULE && ss[i].cssRules[j].selectorText == '#'+rule)
return ss[i].cssRules[j];
}
}
return null;
}

But beware of the problem I mentioned in a comment: this only works when protocol != "file:",

Cannot access cssRules from local css file in Chrome 64

TL;DR: As of Chrome 64 you'll need to use a local development server to test functionality that depends on the CSS Object Model.

Accessing CSS rules in a stylesheet loaded from the local filesystem violates a Cross-Origin Resource Sharing (CORS) policy - but Chrome didn't enforce this until recently, and other browsers don't seem to enforce it yet.

Chrome 64.0.3282.0 (released January 2018, full change list) includes a change to security rules for stylesheets. I couldn't find this change in any changelog less detailed than the full commit list.

Commit a4ebe08 in Chromium is described:

Update behavior of CSSStyleSheet to match spec for Security origin

Spec is here:
https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface

Updated: the following methods now throw a SecurityError if the
style sheet is not accessible:

  • cssRules() / rules()
  • insertRule()
  • deleteRule()

This commit is a fix for the bug Security: Inconsistent CORS implementation regarding CSS and the link element. The linked W3C spec describes in detail where use of the CSS Object Model requires same-origin access.

This is a real security constraint and the solution you posted (online/localhost) is probably the most typical workaround. For more information check out MDN's How do you set up a local testing server? - it discusses why and how to use a local development server to avoid CORS issues.

That said, there's still some open issues and debate around this change.

  • This comment on the original security bug complains that the only way now to detect that the stylesheet is not accessible from JavaScript is with a try/catch.
  • A Chromium bug opened January 23rd (document.styleSheets.cssRules is null even with Access-Control-Allow-Origin: *) suggests there may be an implementation issue with the new security rule that breaks certain workarounds.
  • The spec being implemented seems pretty stable, but it still has "Working Draft" status so who knows where it will land and what other browsers will implement.

Get css rules, chrome extension

Content script of an extension obeys the same cross-origin rules as the page where it runs and just like the page it cannot read cross-origin style sheets. This is by design.

The only reliable method is to use chrome.debugger API with Page.getResourceTree command to get the entire list of loaded resources then use Page.getResourceContent on each returned resource URL to get its actual contents exactly as it was loaded on the page without making a new network request.

The slightly less reliable approach is to use a content script to read entries from document.styleSheets: those that succeed will be same-origin, those that fail will be cross-origin so you can accumulate a list of their URLs and tell the background script to fetch them (the permissions in manifest.json must allow those URLs, for example "*://*/").

I cannot get all the cssRules for some pages

document.styleSheets contains<style type="text/css"></style> as well as <link rel="stylesheet" type="text/css" href="style.css"> so you will not get href from the first one. I would check if those styles are not blank as well, in case they have no cssRules.

document.styleSheets[x].cssRules are null

That's because the style sheets are coming from a different domain. Some browsers (such as Chrome) implement strict cross-domain policies by throwing security errors or setting the cssRules and ownerRule to null when it comes from a different domain...in your case the style sheets come from a CDN

MDN quotes the following in the CSSStyleSheet documentation...

In some browsers, if a stylesheet is loaded from a different domain,
calling cssRules results in SecurityError.

https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet

Uncaught DOMException: Failed to read the 'cssRules' property

In latest Chrome, CORS security rules are applicable for style-sheets also (Similar to Iframe rules).

You can load and render them but, cannot access the content through javascript (If loaded from Cross-Domain ).

If your CSS Stylesheet is from Same domain as of HTML /or included in same HTML file, you will be able to access document.styleSheets[elem].cssRules otherwise it will throw error

Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules

Cross Domain Stylesheet

Cross Domain Stylesheet

Same Domain Stylesheet

Same Domain Stylesheet

Uncaught DOMException: Failed to read the 'rules' property from 'CSSStyleSheet'

This was a good story and a new 'gotcha' for web developers, so I just had to share:

Chrome 64.0.3282.0 (released January 2018, full change list) introduced a change to security rules for stylesheets. I'm irritated that I couldn't find this change in any changelog less detailed than the full commit list.

Commit a4ebe08 in Chromium is described:

Update behavior of CSSStyleSheet to match spec for Security origin

Spec is here:
https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface

Updated: the following methods now throw a SecurityError if the
style sheet is not accessible:

  • cssRules() / rules()
  • insertRule()
  • deleteRule()

This commit is a fix for the bug Security: Inconsistent CORS implementation regarding CSS and the link element. The linked W3C spec describes in detail where use of the CSS Object Model requires same-origin access.

All that said, why was this issue showing up in App Lab? We shouldn't experience any CORS issues, because we only load stylesheets from our own origin:

Chrome network tab showing all CSS requested from the affected page

The final clue was that we couldn't reproduce this issue in a private tab. We started looking at Chrome extensions and realized that some affected users had the Loom Video Recorder extension enabled, which seems to inject its own CSS into the page. Since our (naïve) function was iterating through all loaded stylesheets, it was attempting to access this stylesheet injected by the extension and thus causing the CORS error.

That said, there's still some open issues and debate around this change in Chrome:

  • This comment on the original security bug complains that the only way now to detect that the stylesheet is not accessible from JavaScript is with a try/catch.
  • A Chromium bug opened January 23rd (document.styleSheets.cssRules is null even with Access-Control-Allow-Origin: *) suggests there may be an implementation issue with the new security rule that breaks certain workarounds.
  • The spec being implemented seems pretty stable, but it still has "Working Draft" status so who knows where it will land and what other browsers will implement.

To fix our problem, we just tore out the entire function. We don't support IE9 anymore, and we know all of our supported browsers handle media queries properly.

Related (but not quite duplicate) questions:

  • cannot access rules in external CSSStyleSheet
  • Cannot access cssRules from local css file in Chrome


Related Topics



Leave a reply



Submit