-
Notifications
You must be signed in to change notification settings - Fork 72
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
Constructable Stylesheets #103
Comments
I'm not an expert in this area, but I'm wondering how this relates to "CSS in JS". There are a ton of libraries that do "CSS in JS", then output a component-specific stylesheet (via webpack, babel, or whatever). How does this proposal play with those? |
Hmm, I'm not sure if I'm getting this right, but looks like most CSS-in-JS doesn't work with shadow DOM. The basic idea seems to be similar, though generated CSS-in-JS will be creating a real style element put into the document so it can't cross through shadow boundaries. Also, I don't think we can create complex selectors with CSS-in-JS (probably I'm wrong)? With constructable stylesheets, we can get the full feature of CSS. |
@rakina would it be worth me bringing in some "CSS in JS" folks to comment? I know a few that would be really interested in this, and might have some suggestions about what they need. However, happy to hold off too if you think you are not there yet with the proposal. |
@marcoscaceres Oh, I'd be happy to have more people giving suggestions! Yes please, I think that would be really helpful. Thanks! Also FYI, I intend to bring this topic for discussion in the CSSWG session at TPAC this year (https://wiki.csswg.org/planning/tpac-2018) |
Ok, cool. Let me ping a few devs. Hopefully they will be willing to comment! |
Another thing that might be related to Constructable Stylesheets & CSS-in-JS: CSS Modules WICG/webcomponents#759 |
I think the basic idea here is reasonable, and while it's not clear to me how we'd prioritize it, and I also suspect the specification needs a good bit of further work to be defined precisely enough and integrate properly with other specifications, it seems like a reasonable addition to the platform, so I'd be inclined to mark it as Does that seem reasonable to the others here? |
I think the general idea seems OK. There are probably other ways you could come up with to solve the problem of avoiding duplication of style sheets between different instances of a Web Component, but an API to create individual, sharable style sheets to insert into different shadow trees is a reasonable way to do it. |
I've heard secondhand that webkit folks are opposed to this; I'm not entirely sure where that came from, but curious if @hober knows. |
Most of the opposition was to the "introducing new cascade origin" bit which is gone from the spec IIRC. |
Though not sure if they have any plans or official stance on it. @rniwa maybe knows? |
We had concerns about the specific shape of the API; e.g. |
Note that the cascading order issue is somewhat orthogonal; that is about "lightweight" mechanism to add styles to a custom element without a shadow tree. |
Ah, indeed, sorry I misremembered. Thanks @rniwa :) |
The reason I want Constructable Stylesheet support in Firefox (ASAP) is here. Basically, it eliminates a lot of redundancy that comes with embedding This article has a nice table that shows what's currently missing from Firefox in regards to web components. Also, I found this video. |
I don't expect constructible stylesheets to be a performance improvement over |
Indeed, it is. It will be nice to set the stylesheet using a javascript reference like this. |
In this test, the same stylesheet (bootstrap.css) is loaded twice (one due to the link in head and other due the link in a custom element shadow tree). This behavior occurs on Firefox but is not observed on chrome (where the stylesheet is loaded once) If a stylesheet is linked only from shadow tree (foundation.css) its loaded once in both browsers I identified the css load by using the Network devtool panel. Not sure if it means an extra CSS parse. So:
PS: for a cleaner way to observe the behavior access the codepen debug view |
I don't see any link in the html section of the codepen, but I guess you mean the one in the If so, it is expected to fetch the stylesheet twice, once for the outer document, and once for the inner one. But once the stylesheet is loaded in one of the documents, the you don't see other loads, as expected. I cannot access the debug view:
But I assume it's similar. In any case the behavior of Firefox here is the same as in Chrome, as far as I can tell from the network panels: Firefox NightlyChromeBoth have two loads of bootstrap.css (and thus, I expect, two reparses of the sheet). But as I said there are two different documents involved, which can't access each other via Javascript at all, so it's not something you could solve with constructable stylesheets even if the two documents wanted to cooperate. So I don't really know what you're referring to, or how is it relevant to this issue, but it might (probably) be that I misunderstood the test-case. Mind elaborating? Sharing parsed stylesheets across |
Hi @emilio thanks for your feedback. The default codepen interface adds lots of noise. The debug view shows only the pen html but is only accessible by owners (needs to fork the pen to access it). I've put the cleaned test page here. At the time i created this test, and until yesterday, the bootstrap.css was requested at page load and at first time a custom element with a link or import was added to document. I swear. This was the reason i stopped using shadow dom Today, retesting, bootstrap.css is still requested at page load but not at custom element addition matching the chrome behavior (and probably moving away the performance concern) Sorry for the false alert |
Regarding potential benefits of Constructable Stylesheets over using link or import i see two:
|
How is this helped by constructable stylesheets? I'm confused. Do people just create a giant CSS file, and then chunk it into multiple
You can already do this without constructable stylesheets, fwiw. Code below untested, but something on those lines should do: function sheetLoaded(url) {
return new Promise((resolve, reject) => {
let link = document.createElement("link");
link.rel = "alternate stylesheet";
link.title = "dummy";
link.href = url;
link.onload = function() { resolve(); link.remove(); };
link.onerror = function() { reject(); link.remove(); };
document.head.appendChild(link);
});
}
// ...
await sheetLoaded("foo");
// load shadow trees with <link rel="stylesheet" href="foo"> Though I agree constructable stylesheets provide a less hacky way of doing that. |
FWIW, I can reproduce the issue you mention, only if I've done something like opening the devtools inspector before. And this is because devtools pokes at the document stylesheets using CSSOM, and thus we determine we can't reuse the cached stylesheet, since it may be different. I'll track it down and see if it's avoidable, but if you see something like that, instead of avoiding the feature (or at least on top avoiding the feature) reporting a bug would be useful. |
Take as example how styling works in LitElement. It provides a tagged template literal When element is instantiated, before rendering occurs, it sets the styles defined by This way, before rendering occurs the stylesheets are already loaded and parsed, so no FOUC. Also since the styles are defined as Javascript (tagged template literals) they can be bundled together by, e.g., webpack. Example: //sharedstyles.js
export const baseStyles = css`h1 {color: red};`
export const tableStyles = css`table {color: blue};`
//my-element.js
import { LitElement } from 'lit-element'
import { baseStyles, tableStyles } from 'sharedstyles'
class MyElement extends LitElement {
static get styles() {
return [ css`:host { display: block; }`, baseStyles, tableStyles];
}
} Here's an actual project with this kind of setup: https://github.com/CitizensFoundation/open-active-voting/tree/master/public/src/components . The styles lives in the *-styles.js files |
At the time i was not sure if it was a bug and there's the FOUC issue. Also, since my projects depends on Bootstrap which does not plays well with shadow dom i opted to disable it. But glad to know you are receptive to bug reports |
Sure, but that doesn't avoid any http request. As far as I can tell what happens is:
It's a bit unfortunate that they chose that implementation strategy. The alternative to |
Say we have two version of a webpack app: //sharedstyles.js
export const baseStyles = css`h1 {color: red};`
export const tableStyles = css`table {color: blue};`
//my-element.js
import { LitElement } from 'lit-element'
import { baseStyles, tableStyles } from 'sharedstyles'
class MyElement extends LitElement {
static get styles() {
return [ css`:host { display: block; }`, baseStyles, tableStyles];
}
} In the above using styles with bundle.js Now the same app using link to style: //my-element.js
import { LitElement, html } from 'lit-element'
class MyElement extends LitElement {
render() {
return html`
<link rel="stylesheet" href="base-styles.css">
<link rel="stylesheet" href="table-styles.css">
<link rel="stylesheet" href="my-element.css">
`
}
} You have four requests: bundle.js So, the number of requests of the app will increase together with the number of styled components.
You are right about this. This is one of the reasons i use web components with shadow dom disabled and still use a global stylesheet with sass (it works fine BTW). Firefox is my main browser and fully supports it. I ended here to know status of |
For me, the most important aspect of this, is the ability for the shadowDOM to acquire its style(s) via javascript variables, and not by parsing html "style or link" tags. Take a look at this example. My favorite line in that example is this one: "styles", is a javascript variable! So, you can download or dynamically generate the style sheet once, and then have every web-component-instance consume that same single memory-reference. If I have 1000 instances of a web component on a single page. Those instances should NOT do any of the following:
CSS is used to style HTML. And the most efficient way to associate a particular CSS style to multiple DOM Element Nodes, is to have each of those nodes have memory references pointing to that single CSS Style instance. In other words, via a javascript variable. |
Added an issue in lit-element lit/lit-element#761 |
Why is this bug "closed"? If I open up a console in Firefox 68.0.2, and type: I get this error: As I explained here, the ability to reference a stylesheets using a javascirpt variable is fundamental and essential for performance sake when styling numerous instances of a shadowRoot-driven custom element. This stuff works great in Chromium. Has Firefox decided not to implement this? |
This repository covers positions on emerging web standards in the discussions of standards development, not implementation in Firefox, which is covered by bug 1520690 |
@dbaron Thank you for explaining and linking to the bug above. |
Request for Mozilla Position on an Emerging Web Specification
Other information
There might be small API changes due to current open issues but the basic idea should stay the same, that is to allow creating
CSSStyleSheet
objects and use them inDocumentOrShadowRoot.adoptedStyleSheets
. See also explainer.The text was updated successfully, but these errors were encountered: