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.
Related videos on Youtube
Comments
-
Puddle over 3 years
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:
- Works when files are online/localhost.
- Works with other browsers. (i.e. Internet Explorer, Microsoft Edge, Firefox)
- chrome --allow-file-access-from-files
-
Teemu over 6 yearsWhat does the Network tab in the Dev Tools say, is the style sheet loaded?
-
Puddle over 6 yearsthe stylesheet is loaded yes.
-
Teemu over 6 yearsAne error messages in the console then?
-
Puddle over 6 yearsUncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules at window.onload
-
Teemu over 6 yearsWhich browser are you using? Seems to work fine in FF ..?
-
Puddle over 6 yearshave you tried running it yourself? you should be able to see what's wrong.
-
Petrashka Siarhei over 6 yearsMay be incorrect path to css file or your server didn't send file to browser.I agree with Teemu, look status file in devtools
-
Puddle over 6 yearsthe css is completely fine and loaded. no incorrect path.
-
Petrashka Siarhei over 6 years@Pubble, add your css, please.
-
Teemu over 6 yearsFor 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.
-
Puddle over 6 yearswhy is the title useless? it's what it is. what do you suggest?
-
Teemu over 6 yearsYour browser is still missing, I can't reproduce the issue with any browser installed on my machine ... not even in IE.
-
Teemu over 6 yearsHonestly, 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, but the Chrome version is below 53 ... I can agree with cale_b's edit, the question is much better with the new title.
-
Huangism over 6 yearsThe 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 ? -
Puddle over 6 yearsthere's a flag you can use on chrome, but it's apparently dangerous. "Leaves your file system open for access" stackoverflow.com/a/33801287/9312988 but there's another solution below, to use an extension "Web Server for Chrome".
-
halfer about 6 yearsHelpful 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 - How to Ask and minimal reproducible example are very good.
-
Puddle about 6 yearsdo you recommend i delete this one?
-
Alex over 3 years@Puddle Is there any reason you reverted my edit?
-
user14471901 over 5 yearsThats 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?
-
Brad Buchanan over 5 yearsBrowsers get to choose how to handle this situation. The W3C CORS spec gets its definition of an "origin" from RFC6454 "The Web Origin Concept" which says the origin of a file:// URI is implementation-dependent.
-
Brad Buchanan over 5 years