Skip to content
This repository has been archived by the owner on Oct 21, 2022. It is now read-only.

Cannot use inline 'onload' because of CSP #312

Closed
petervtzand opened this issue Feb 20, 2020 · 6 comments
Closed

Cannot use inline 'onload' because of CSP #312

petervtzand opened this issue Feb 20, 2020 · 6 comments

Comments

@petervtzand
Copy link

When you have a CSP without unsafe-inline, you cannot use onload inline. This it will throw an error, and therefore not load the css.

So the following cannot be used.

<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">

So then I thought of a solution, where I use an event listener that is triggered when the css is loaded:

<link id="async-css-loading" rel="stylesheet" type="text/css" href="/path/to/my.css" media="print"/>

<script nonce="{{nonce}}">
  document.getElementById("async-css-loading").addEventListener("load", function(){
    this.media = "all";
  });
</script>

This seems to work, but will I get the same performance? If this does work maybe the documentation can be updated for people who don't want to add 'unsafe-inline' do their CSP?

@scottjehl
Copy link
Member

Looks good! Thanks for noting. It should work the same yes, but I'm not sure if there's a possibility of the CSS loading from cache before the onload event is bound. It does make me wonder if a timeout might be more dependable, since it's not onload in particular that needs to be used so much as some event that happens after the CSS file is requested.

Worth testing.

Anyway, I'd love a readme edit if you'd like to. Otherwise we'll aim to get to it when we can.

@gr8bit
Copy link
Contributor

gr8bit commented Mar 12, 2020

Nice find & workaround @petervtzand ! One question though, why don't you "activate" the stylesheet in the link by setting the rel-attribute to "stylesheet" rather than changing the media attribute?

@petervtzand
Copy link
Author

I've used this example of the filament group: https://www.filamentgroup.com/lab/load-css-simpler/. This seems to be their new and simpler approach.

@lubomirblazekcz
Copy link

lubomirblazekcz commented Mar 17, 2020

Here is a variant if you have multiple styles

    <script nonce>
        Array.prototype.slice.call(document.querySelectorAll("[data-loadcss]")).map(function (e) {
            e.addEventListener("load", function() {
                this.media = "all"
            });
        })
    </script>

or shorter es6 syntax

    <script nonce>
        [...document.querySelectorAll("[data-loadcss]")].map((e) => e.addEventListener("load", (e) => e.target.media = "all"));
    </script>

@lubomirblazekcz
Copy link

Btw, I've noticed a weird bug where event listener did not trigger in Edge 18. So I've had to add this workaround. Works with onchange though, weird.

            if (navigator.userAgent.match("Edge/")) {
                e.media = "all";
            }

@Macleykun
Copy link

Macleykun commented Nov 11, 2021

Here is a variant if you have multiple styles

    <script nonce>
        Array.prototype.slice.call(document.querySelectorAll("[data-loadcss]")).map(function (e) {
            e.addEventListener("load", function() {
                this.media = "all"
            });
        })
    </script>

or shorter es6 syntax

    <script nonce>
        [...document.querySelectorAll("[data-loadcss]")].map((e) => e.addEventListener("load", (e) => e.target.media = "all"));
    </script>

Sorry for necromancing an old issue with a (unrelated) question.
But using the es6/other variant like just including it to the bottom will async/inline onload but not cause csp to break?
Like no adjustments needed? Just chug it to the bottom? Or should it be placed in the header?

Again, sorry for reviving an issue with a unrelated (noob) question. I do look forward to your reply!

I've tried to implement it here: https://github.com/TheVoxSiren/voxsiren.net/blob/main/index.html#L7
But i feel like it's not really doing anything?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants