Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add <link disabled> stylesheets to document.styleSheets #9977

Open
jfbrennan opened this issue Dec 4, 2023 · 4 comments
Open

Add <link disabled> stylesheets to document.styleSheets #9977

jfbrennan opened this issue Dec 4, 2023 · 4 comments
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest

Comments

@jfbrennan
Copy link

jfbrennan commented Dec 4, 2023

What problem are you trying to solve?

I am trying to disable a stylesheet on page load with HTML - <link rel="stylesheet" href="..." disabled> - but once a condition is met at runtime, enable that stylesheet with JavaScript via document.styleSheets.item(i).disabled = false.

Currently, <link disabled> prevents the stylesheet from inclusion in document.styleSheets. I find this odd. Developers must resort to interacting with the <link> elements directly instead of the CSSStyleSheet objects, like they can with stylesheets that weren't initially disabled in the document.

What solutions exist today?

Disable a stylesheet on page load with HTML <link disabled> then use a selector API, like getElementById, to remove the disabled attribute.

How would you solve it?

My intuition was that I could disable a stylesheet with HTML - <link disabled> - and it would become a CSSStyleSheet object with its disabled property set to true and still be included in document.styleSheets and its styles NOT applied to the document.

Setting sheet.disabled = false would then apply the styles. When the browser first downloads a disabled stylesheet is not a concern as sheet.cssRules could be null or already set when the stylesheet is enabled. Always downloading could avoid a delay when first enabling, but then again delaying the download may be desirable as well.

Anything else?

No response

@jfbrennan jfbrennan added addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest labels Dec 4, 2023
@flavi1
Copy link

flavi1 commented Dec 6, 2023

Do you realy need a CSSStyleSheet object for disabled stylesheets ? Or are you just looking for a simple way to list enabled/disabled stylesheets?

const AllStyleSheets = document.querySelectorAll('link[rel~="stylesheet"], style')
AllStyleSheets.forEach((sEl) => {
    console.log(sEl.disabled) // changeable boolean value
    console.log(sEl.sheet)  // CSSStyleSheet or null
})

If it's a performance issue, you probably wants to disable some stylesheets after their load. Then you don't have to download them again. Ex with a custom attribute data-to-disable :

const AllStyleSheets = document.querySelectorAll('link[rel~="stylesheet"][data-to-disable], style[data-to-disable]')
AllStyleSheets.forEach((sEl) => {
    sEl.addEventListener('load', (ev)=>{
        ev.target.disabled = true;
    })
})

Not tested, but should work...

@flavi1
Copy link

flavi1 commented Dec 7, 2023

There is maybe another alternative. LinkHTMLElement is designed to load external ressources (not only CSS). I don't know how browsers caches them, and make it reusable later, but you can try to put the "stylesheet" on the rel attribute later.

A last idea : Try to use rel="preload", then add the as="style" attribute later, or remove a disabled attribute later.
see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/preload

I hope it will help you.

@jfbrennan
Copy link
Author

jfbrennan commented Dec 11, 2023

@flavi1 thank you, there are many ways to do what we needed to do and we did. I opened this issue because of the inconsistent behavior, which I believe is incorrect and unintuitive for a developer.

For example, a developer includes this at the top of their document:

<link rel="stylesheet" href="https://assets.com/a.css">
<link rel="stylesheet" href="https://assets.com/b.css" disabled>
<link rel="stylesheet" href="https://assets.com/c.css" media="screen and (max-width: 600px)">

That results in:

// document.styleSheets
{
  0: {
    type: 'text/css', 
    href: 'https://assets.com/a.css', 
    media: {mediaText: "", ...}, 
    disabled: false, 
    ...
  },
  1: {
    type: 'text/css', 
    href: 'https://assets.com/c.css', 
    media: {mediaText: "screen and (max-width: 600px)", ...}, 
    disabled: false, 
    ...
  }
}

Note that b.css is not there at all and the others have defaulted to disabled: false.

Two of my three <link> elements were parsed and constructed into CSSStyleSheet objects and added to document.styleSheets. Feels like a bug that b.css was not. I 100% expected to find:

{
  0: {
    type: 'text/css', 
    href: 'https://assets.com/a.css', 
    media: {mediaText: "", ...}, 
    disabled: false, 
    ...
  },
  1: {
    type: 'text/css', 
    href: 'https://assets.com/b.css', 
    media: {mediaText: "", ...}, 
    disabled: true, // <-- In the disabled state, but <link> was still parsed and constructed like the others 
    ...
  },
  2: {
    type: 'text/css', 
    href: 'https://assets.com/c.css', 
    media: {mediaText: "screen and (max-width: 600px)", ...}, 
    disabled: false, 
    ...
  }
}

That seems very much like the way it should be.

Now, does a browser download a disabled link stylesheet or not? Well, no, browsers do not. Ok, I agree with the reasoning for that, but why does that mean we shouldn't include b.css as a disabled CSSStyleSheet in document.styleSheets? There are three reasons why I think that behavior is wrong and unintuitive:

  • You can later set disabled on a CSSStyleSheet and it doesn't get removed from document.styleSheets, so it's not like all disabled stylesheets are excluded from this list
  • a.css and c.css are fake files that never downloaded (they 404'ed), and yet those link elements are still parsed and constructed into objects and included in the stylesheet list
  • Empty files, like if a.css downloaded successfully but was empty, are also included

@flavi1
Copy link

flavi1 commented Dec 12, 2023

Yes, I agree. Since a CSSStyleSheet can effectively refer to a not yet downloaded CSS, and the disabled property exists, it seems more consistant to have an instance for each StyleSheets, including disabled StylesSheets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition/proposal New features or enhancements needs implementer interest Moving the issue forward requires implementers to express interest
Development

No branches or pull requests

2 participants