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:
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.
try/catch
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With