22

Here's a simple example of the problem:

<html>
<head>
<link rel='stylesheet' href='myStyle.css'>
<script>
window.onload=function(){
    try{
        alert(document.styleSheets[0]); // works
        alert(document.styleSheets[0].cssRules); // doesn't even print undefined
    }catch(e){alert(e);} // catch and alert the error
}
</script>
</head>
<body>
</body>
</html>

myStyle.css body{background-color:green;}

The script works fine with <style></style>

Solutions:

  1. Works when files are online/localhost.
  2. Works with other browsers. (i.e. Internet Explorer, Microsoft Edge, Firefox)
  3. chrome --allow-file-access-from-files
Puddle
  • 2,993
  • 1
  • 19
  • 32
  • What does the Network tab in the Dev Tools say, is the style sheet loaded? – Teemu Feb 12 '18 at 19:07
  • the stylesheet is loaded yes. – Puddle Feb 12 '18 at 19:11
  • Ane error messages in the console then? – Teemu Feb 12 '18 at 19:14
  • 2
    Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules at window.onload – Puddle Feb 12 '18 at 19:15
  • Which browser are you using? [Seems to work fine in FF](https://jsfiddle.net/vu77efud/) ..? – Teemu Feb 12 '18 at 19:15
  • have you tried running it yourself? you should be able to see what's wrong. – Puddle Feb 12 '18 at 19:15
  • May be incorrect path to css file or your server didn't send file to browser.I agree with Teemu, look status file in devtools – Petrashka Siarhei Feb 12 '18 at 19:16
  • the css is completely fine and loaded. no incorrect path. – Puddle Feb 12 '18 at 19:17
  • @Pubble, add your css, please. – Petrashka Siarhei Feb 12 '18 at 19:20
  • For some reason Chrome seems to show an empty object at jsFiddle, and it also complains about a timed out resource loading. FF and Edge are fine with the code. – Teemu Feb 12 '18 at 19:23
  • why is the title useless? it's what it is. what do you suggest? – Puddle Feb 12 '18 at 19:25
  • 2
    Your browser is still missing, I can't reproduce the issue with any browser installed on my machine ... not even in IE. – Teemu Feb 12 '18 at 19:28
  • Honestly, I found "chrome" for a couple of seconds before your last comment. Anyway, I can't reproduce the issue in Chrome 63. There are some limitations for StyleSheets mentioned [at MDN](https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/styleSheets), but the Chrome version is below 53 ... I can agree with cale_b's edit, the question is much better with the new title. – Teemu Feb 12 '18 at 19:43
  • The error can be reproduced on Mac FF or chrome. Even when I inspect this page and paste the js code in console, I get `SecurityError: The operation is insecure` on FF on Mac. You are using Mac right @Puddle ? – Huangism Feb 12 '18 at 20:47
  • there's a flag you can use on chrome, but it's apparently dangerous. "Leaves your file system open for access" https://stackoverflow.com/a/33801287/9312988 but there's another solution below, to use an extension ["Web Server for Chrome"](https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en). – Puddle Feb 12 '18 at 20:55
  • Helpful note on deleting questions: it's OK to delete closed posts if you are sure they will not be helpful to readers in the future. You may know that downvotes can contribute to a Stack Overflow account being post-throttled or post-banned; it's worth knowing also that deleted questions still contribute to that algorithm. So, if you can improve your old questions, that is better than just deleting them. Also, read the help centre if you can - [ask] and [mcve] are very good. – halfer Feb 27 '18 at 17:56
  • do you recommend i delete this one? – Puddle Feb 27 '18 at 18:03
  • @Puddle Is there any reason you reverted my edit? – Alex Nov 01 '20 at 02:29

1 Answers1

39

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.
Brad Buchanan
  • 1,475
  • 1
  • 15
  • 22
  • 7
    Thats all well and good, but why does accessing the CSS file from a locally loaded document (eg SVG graphic), all via the FILE:// protocol, trigger a CORS violation? I'm viewing an SVG graphic from my local file system (graphic.svg) via the Windows file explorer (eg open with Chrome). The SVG graphic references the file "my.css" in the same directory as the "graphic.svg" file. The ECMAscript in the SVG graphic tries to access the cssRules via: document.styleSheets[0].cssRules and gets a DOMException. Seems loading everything from the same origin: FILE://, so why the error? – Minok Sep 24 '18 at 22:56
  • 3
    Browsers get to choose how to handle this situation. The [W3C CORS spec](https://www.w3.org/TR/cors/) gets its definition of an "origin" from RFC6454 "The Web Origin Concept" which [says the origin of a file:// URI is implementation-dependent](https://tools.ietf.org/html/rfc6454#section-4). – Brad Buchanan Sep 25 '18 at 23:31
  • See also https://stackoverflow.com/questions/48313084/what-is-the-same-origin-policy-for-file-uris – Brad Buchanan Sep 25 '18 at 23:37
  • the inmates are running the asylum – capr Feb 19 '23 at 20:35