-
Notifications
You must be signed in to change notification settings - Fork 25
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
Should adoptedStyleSheets be ordered before other style sheets in the tree, instead of after? #93
Comments
They have to be put somewhere, and putting them before all the stylesheets coming from |
Sounds like this is a subjective issue, so here's my preferred color for the bike shed: I conceptually think of the style sheets in a single root as if they were concatenated into a single style sheet since they pretty much work this way. Adding a style sheet to So, if we use this example: const sheet1 = new CSSStyleSheet();
sheet1.replaceSync(".foo { color: red; }");
const div = document.createElement("div");
const shadowRoot = div.attachShadow({ mode: "open" });
shadowRoot.adoptedStyleSheets = [sheet1];
shadowRoot.innerHTML = `
<style>.foo { color: blue; }</style>
<span class="foo">Hello!</span>
`; It feels more like it should be: @import 'data:text/css,.foo { color: red; }';
.foo { color: blue; } than: .foo { color: blue; }
@import 'data:text/css,.foo { color: red; }'; I think this sentiment becomes even more applicable if CSS Modules become a thing. But I totally recognize that it's not critical since I could just stop adding inline |
I see where you're coming from within shadow roots, but consider the issue on the outer page, where If we could somehow put it in the middle, where everything in the Putting JS-managed stuff after HTML-managed stuff is the general pattern for this sort of thing, so that's what we went with. |
(Really, what we want is the ability to tag the adopted stylesheet as part of a specific Cascade Origin, so you could set things up as being "user-agent" level, and thus automatically overridden by anything at author-level, such as |
What if Main document: const externalStyles = document.createElement('style');
externalStyles.adoptedStyleSheets = [a, b, c];
// If you want adopted styles after everything else you've imported:
document.head.appendChild(externalStyles); In a ShadowRoot: const div = document.createElement("div");
const shadowRoot = div.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<style>.foo { color: blue; }</style>
<span class="foo">Hello!</span>
`;
const externalStyles = document.createElement('style');
externalStyles.adoptedStyleSheets = [a, b, c];
// If you want adopted styles before everything in the root:
shadowRoot.insertBefore(externalStyles, shadowRoot.firstChild); You could put them in multiple places if that's what you needed: <style id="alwaysLoses"></style>
<style>.foo { color: red; }</style>
<style id="alwaysWins"></style>
<script>
document.getElementById('alwaysLoses').adoptedStyleSheets = [a, b];
document.getElementById('alwaysWins').adoptedStyleSheets = [c, d];
</script> edit: Removed an incorrect line in the second example. |
If you're going to give them before/after locations in the DOM tree, they should just be DOM nodes. For example, HTMLStyleElement. |
CSSStyleSheet could have a method that produces a new HTMLStyleElement associated with the style sheet. Using const div = document.createElement("div");
const shadowRoot = div.attachShadow({ mode: "open" });
shadowRoot.innerHTML = `
<style>.foo { color: blue; }</style>
<span class="foo">Hello!</span>
`;
const externalStyles = document.createElement('style');
externalStyles.adoptedStyleSheets = [a, b, c];
shadowRoot.prepend(externalStyles); would become const div = document.createElement("div");
const shadowRoot = div.attachShadow({ mode: "open" });
shadowRoot.adoptedStyleSheets = [sheet1];
shadowRoot.innerHTML = `
<style>.foo { color: blue; }</style>
<span class="foo">Hello!</span>
`;
shadowRoot.prepend(...[a, b, c].map(sheet => sheet.createLinkedStyleElement())); Is that kind of what you were thinking? |
Yes, although I'm not sure there's too much value in indirecting through CSSStyleSheet instead of just creating a HTMLStyleElement directly. |
I was thinking that the node created by |
I was thinking even simpler: just use HTMLStyleElement only, don't ever use a CSSStyleSheet apart from htmlEl.sheet. |
I'm not sure I follow - could you give an example? |
In fact, I thought it behaved like user agent's stylesheets. While this problem is more important in the |
I think something like |
Yeah, the reasoning in this thread seems fairly convincing. Like I said in my earlier comment, I think the current placement (page, then adopted) makes the most sense for the outermost page, but within a shadow root the reasoning is different. (Specifically, So I support some way of having adopted sheets go before the inline sheets. Whether that's by shifting where they go in general, or by adding a secondary attribute that places them in a different spot, I don't have a real opinion on. |
Sounds reasonable to have overridable styles. What if instead of changing/adding another type of So you would have a new option I don't have any strong preference though, probably having two kinds of |
I don't have strong feelings, but am confused by this use case. Why would a web component ever modify a shared document-level resource? Put them in the shadowRoot.adoptedStyleSheets. Then they will behave similar to UA styles. |
Also no personal preference, maybe something like order (analogous to css order) can cover this and other use cases better.
Ideally all components would use shadow-dom, but in practice it’s not possible. Believe me, we have tried really hard. The lack of :host-context(), style any descendant (slotted only styles direct children), integration with form (I know it will get better), developers might want some flexibility. In addition apps (not isolated components) components usually work better without shadow-dom, otherwise all pages content is inside the shadow-dom. For SEO reasons is still useful to build web components without shadow-dom enabled. In any case, for anything that is more complex than a simple web component, there are many good reasons to avoid it. In stencil, developers can use native shadow-dom (recommended), scoped (simulated shadow-dom using normal css) and normal. In both scoped and normal, and polyfilling native shadow-dom, the stylesheet is attached to the document. However, in the shadow-dom use case I would also expect a inlined <style> to be applied after, and override the adopted styles. Notice that constructable stylesheets might be used most of the times by frameworks or libraries. But developers (users) will still use inlined styles to override certain default because the ergonomic are a little better. |
Thanks for clarifying!
I worry that at least two of these are working around unimplemented features in some browsers. Adding new features to the spec will not help with that, as those browsers will not implement the new features either. Could you expand on the "style any descendant" problem, and how using document-level stylesheets solves it? |
I also think modifying or picking a single behavior for a shared style sheet is kind of strange and would be a problem because that chosen behavior would apply to all users of that style sheet. For example, if a package distributes modules exporting CSSStyleSheets, then that package has to decide the single behavior that all of its users use. One workaround would be to make the package export a function that generates a CSSStyleSheet with the desired options, but that starts cutting into the value of sharing them because you need a copy for each distinct set of options requested. |
I guess that's fine, we support Constructable Stylesheets because they actually help the performance for most of our users (Chrome and Android). We fallback to the old slower behaiour in other browsers. The problem would be to not even use Constructable Stylesheets in Chrome because it does not cover our use case.
So withing shadow-dom,
but in shadow-dom, ::slotted(h1) will not target a nested h1 element. |
The CSS Working Group just discussed
The full IRC log of that discussion<stantonm> topic: Should adoptedStyleSheets be ordered before other style sheets in the tree, instead of after?<astearns> github: https://github.com//issues/93 <stantonm> github: https://github.com//issues/93 <stantonm> heycam: spec says orderering of stylesheets should be ?, but actually should it be other way around? <heycam> https://github.com//issues/93#issuecomment-487772869 <bkardell_> q+ <stantonm> TabAtkins: my comment says make sense to put after <stantonm> emilio: don't think there's a strong reason for one or other <stantonm> hober: agree, but is there consistency arguments? <stantonm> TabAtkins: maybe related to @font-face, which is after <astearns> ack bkardell_ <stantonm> bkardell_: talking about shadow root and document styles, strangely related - some things bleed through, some blocked <stantonm> ... not sure I get what ordering means <stantonm> ... would like them to come before <stantonm> ... different use cases, adopt styles from outside <stantonm> TabAtkins: all sheets that come from markup come before adopted style sheets <stantonm> bkardell_: we want to use these for UA equivilent, seems like not the right move <stantonm> TabAtkins: adopted style sheets help when people put things directly in shadow dom <stantonm> ... component usage will move to adopted style sheets, gives full control <stantonm> ... if you use style inline, it's baked into the template <stantonm> ... similar to link style sheet in head, where you override with adopted <stantonm> ... both ordering can make sense, no strong argument <stantonm> bkardell_: we don't know which is correct <stantonm> hober: if we don't know, ask the author <stantonm> ... implies two sets of adopted style sheets, seems complex <stantonm> ... not sure if additional complexity is worth it <tantek> present++ <stantonm> TabAtkins: don't need two sets, just move from shadow root to adopted <stantonm> bkardell_: can you do adopted style sheets outside shadow dom <stantonm> TabAtkins: yes <stantonm> hober: summarizing = after, if they want before have to specify <stantonm> RESOLUTION: constructed style sheets to always go after <TabAtkins> astearns: And if we realize that authors do ahve common need to put the adopted ones first, we're free to add a knob for that. |
I'm coming late here (apologies, I've been living under a rock for the past year). Couldn't the adoptedStyleSheets be placed in the cascade as if they were part of style elements in the the root's That would give authors some flexibility regarding their overidability, and well defined, non-arbitrary semantics. As an author, being able to put styles between the head and the body makes a lot of sense from an overridability standpoint. You could also make them visible (but read-only, or even opaque) in the |
Adding some more thoughts: while the |
Another vote for having these appear before style tags (or, alternatively, giving client code control over the ordering). My use case is a library that injects styles but expects users to occasionally want to override those with regular old style sheets. |
Since that'll give our injected styles a higher precedence than regular style sheets (WICG/construct-stylesheets#93). Issue codemirror/dev#360
The problem was caused because when we switched to using static styles, those are adopted stylesheets, which have higher precedence than style blocks in the shadowRoot (see WICG/construct-stylesheets#93). That meant the style block wasn't actually overriding the default styles for card-renderer. card-renderer container auto-adds a class of the current card type. This allows a pattern of `.${CARD_TYPE_mytype} ` preprended in front of style selectors to increase specificity. That machinery is also used for CARD_TYPE_SECTION_HEAD and CARD_TYPE_WORKING_NOTES, the only two users of styleBlock. (Note that working-notes styling also broke in c28375e but I hadn't noticed before now). Part of #453.
Since that'll give our injected styles a higher precedence than regular style sheets (WICG/construct-stylesheets#93). Issue codemirror/dev#360
From https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets:
Is there a particular reason that style sheets in
adoptedStyleSheets
are ordered after style sheets from<style>
s in the associated tree? AFAICT,adoptedStyleSheets
is being designed primarily as a mechanism for sharing style sheets amongst many elements, but it feels strange that shared styles would take precedence over styles that are certainly only applicable to a particular instance (i.e.<style>
in the associated tree).p.s. Yes, you could just add your instance-specific style sheets to the end of the instance's
adoptedStyleSheets
instead of inserting them into the tree, but why is that necessary?The text was updated successfully, but these errors were encountered: