-
Notifications
You must be signed in to change notification settings - Fork 682
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
[css-cascade] What are the proper "levels" for managing Cascade Layers? #4969
Comments
Manually capturing an important point of @fantasai's: we should design with the assumption that this is applied at the file level, because we definitely need to solve that and it'll be kinda tricky. Controlling origins within a file with at-rules is comparatively simpler; whatever mechanics we work out for between-file handling should trivially translate to within-file. |
The CSS Working Group just discussed The full IRC log of that discussion<Rossen_> Topic: What are the proper "levels" for managing "custom origins"?<Rossen_> github: https://github.com//issues/4969 <myles> jensimmons: I like thinking of this practically. Bootstrap wants to use this, and it makes multiple custom origins inside of itself. This is given off to an author. As miriam and I were talking through, we have nesting, bootstrap has a file, and many imports, each one has a level as custom origin, then you put that into an author project, then an author project has its own levels, and that has its own nesting. That is just a lot of complexity. <myles> jensimmons: Maybe instead, it could be that each origin is in a separate CSS file. There's not a need for particular properties be in one origin and others in antoher origin within the same file. The files could be in its own origin, or multiple files could be in the same origin. This could be part of the <link> element <astearns> if we go with this idea then using the 'sources' name makes even more sense <myles> jensimmons: If bootstrap wants this, they would give you an HTML template that is a suggestion <hober> q+ <myles> miriam: I've gone either way in that conversation. Advantages to nesting are that the final user gets some final control while other parts of the system can still use the tools. So a design system or at ool like bootstrap could have its own internal layering and a user could subsume those layers into their own project. That's a use case <fantasai> I think, we should think about this as all being in separate files for now, for simplicity. We can always add syntax for "embedding" such files into a document later once we figure everything else out. But should definitely be able to pull in the files through a CSS style sheet -- this is a CSS feature, not an HTML feature. <myles> miriam: It is clear that that interacts with how these would be set. IF they are only set in HTML there is no concern for the nesting. They're set at the final point of import or <link>. If we start allowing them to be set internally somewhere, then we have to allow the nested use case because it would not be good if bootstrap could create high origins and i have to fight their origins and we end up in a new battle over control. THe author needs final say <florian> q+ <myles> miriam: Either they're set jsut there, or we have to handle the nested siguation <myles> s/siguation/situation/ <myles> AmeliaBR: Which of these can be expanded on later? <myles> AmeliaBR: Having something that could be an attribute on <link> or @import or something like that, we could have that, and we could add an @rule later. <myles> AmeliaBR: I'm not sure how easy it would be the other way around. <myles> AmeliaBR: Another issue was about having a sensible upgrade path. That's related. <myles> AmeliaBR: How can we keep it simple to start while still adding the potential for new features if they turn out to be required. <TabAtkins> q+ <florian> q- later <myles> hober: I wanted to echo something florian said. Fundamentally, this feature adds complexity in an area which is already complex and confusing. My inclination is to do the simplest possible thing. Regarding if there should be nesting, or sections, etc. The simplest that is possible is what we should do here. I like the file-wide, the entire file is one one origin idea. Should we be specify at @import time, and how tod o that, my inclination for simplicity wars <myles> with my inclination to not diverge <link> from @import. Those shouldn't diverge. If something can be part of <link> but not @import, that's a sign we've failed. <heycam> q+ <Rossen_> ack hober <AmeliaBR> qq+ <myles> hober: Where I'd like to end up is either some kind of file-wide delaration at the top of a style sheet and no change to any import mechanism, or an equivalent change to all import mechanisms, and no ability to declare it file-wide (only declared by the importer) <bkardell_> +1 to tess' points <faceless2_> +1 as well <fremy> qq+ too <Rossen_> ack AmeliaBR <Zakim> AmeliaBR, you wanted to react to hober <fremy> qq+ <Rossen_> ack too <myles> AmeliaBR: To clarify, When I was talkin about @rule, I was talking like @supports or @media groups a bunch of declarations. I agree that <link> and @import should be functionally equivalent. That's not 100% everything in control of the HTML author, but we have a restriction on that saying that @import need to go at the top so there's a clear source order. <myles> fremy: I don't think it makes a lot of sense to put it on <link>. It makes more sense inside the document. All the sub origins you have and their order. That's different from each single file to add all these rules in one origin. Each CSS file should be able to put rules in each origin if needed. The HTML could add a <meta> tag to list all the origins. The stylesheet shouldn't define the origins. That should be in the HTML itself. <Rossen_> ack fremy <Zakim> fremy, you wanted to react to AmeliaBR <Rossen_> ack fantasai <heycam> q- <myles> fantasai: If this is a CSS feature it should be possible to do in CSS <myles> fantasai: It should be possible to link to a stylesheet and that pulls in everything that's necessary for the entire documetn. Everything we do should have CSS syntax. <heycam> q+ <myles> fantasai: It might be possible to have segments of a single file in different origins. But now we shoudl think of them all in separate files beacuse we will need for that. Creating syntax for blocks inside a file will be easier if we figure it out at the file level. <dauwhe> q- === <tantek> q? <Rossen_> ack TabAtkins <myles> TabAtkins: 1. Strong agreement with fantasai. All great stuff. <myles> TabAtkins: Regarding simplest possible. I generally agree with hober. We shouldn't overengeineer this for fanciness sake. But it needs to handle modularity sufficiently well. <fantasai> +1 to Tab <jensimmons> q+ <myles> TabAtkins: Bootstrap needs to origin their own origins 0-6, and an author needs to work around that by putting code above or around it. But what if you're using two libraries? They will conflict and do something bad. SOme degree of nesting or scoping is going to be necessary unless we want to repeat the z-index wars again <dbaron> +1 to Tab on nesting <myles> TabAtkins: That will be a requirement for the final solution <myles> hober: <makes a joke> <leaverou> If two libraries colonize the same origin space, would there be a way for the end user (author) to order these origins? <myles> miriam: It's worth remembering that in the discussion of complexity because flexbox is complex because people are using it to do grids. It's a question of "are we solving the problem." It seems less complex if we solve the problem <Rossen_> ack florian <fremy> <meta name="css-origins" value="reset bootstrap-reset some-lib-reset bootstrap-styles my-site-styles" /> <myles> florian: Therea re two aspects to nesting. 1. Once the layers are in the right place, do we need nesting to do something useful interms of !important fighting itself or not. 2. Figuring out where they fit <dbaron> leaverou, I think that's the feature Tab was just saying is essential <fremy> ... then in the css @origin (bootstrap-reset) { ... } <TabAtkins> leaverou, yup, that's what I just mentioned <myles> florian: It seems to me that we might need nesting for the seond one but not for the first one. If bootstrap wants a bunch of layers, that's reasonable. The user of bootstrap doesn't need to know hwo the layers works. But we odn't need multple layers of !important interact iwth themselves and not wtiht the users' code. So, in teh end, you might not want bootstrap1, bootstrap2, etc. When someone imports bootstrpa, they decide boostrap is below them and they go <myles> on top, without having to worry about internals of boostrap <myles> florian: THis doesn't mean !importance of boostratp needs to be inside that <Rossen_> q <myles> florian: What we should be looking for is using nesting to figure out where the levels fit <myles> fremy: I don't like that because if bootstrap resets its styles, my library wants to put styles between those two, and that would be impossible in this idea <fremy> q+ <tantek> What if Bootstrap's architecture is all by itself overly complicated and fundamentally broken? Optimizing/sovling for Bootstrap may be futile <Rossen_> ack heycam <myles> heycam: Responding to point about having an origin per file. I agree with hober and others who are saying it would be good to concentrate on something that's simple but extendable in the future if we find out we need thse complications. <tantek> I'd rather we make something simple that enables new developers to create something much easier to use that makes Bootstrap obsolete and abandoned. <myles> heycam: But for the origin per file thing, if we're following the fule that we should ahve CSS syntax for everything we do, then we just need to be careful to design some syntax that doesn't just apply to a file at the time, but is something liek an @rule that is self contained <tantek> s/fule/rule <tantek> s/ahve/have <TabAtkins> "Nesting" isn't necessarily the right concept here (that does imply that all the sub-layers go in one spot), but rather that the outer page can control where exactly a sub-project's layers go in the overall page's layer stack. <myles> heycam: It's common for bundlers to concatenate CSS stylesheets that get fetched over the network. We've seen problesm with that int he future. Something that clearly contains the rules in teh stylessheet is recommended. <tantek> s/liek/like <myles> Rossen: I agree. <Rossen_> ack jensimmons <fantasai> +1 TabAtkins <fremy> q- <myles> jensimmons: About making separate origins in separate files, if we don't do that, if we do allow segments of CSS in one file to be in diferent origins. Maybe we can name origins like variables, to explain how they act, or maye it's a set of numbers, the desire to keep it as simple as possible is good. <myles> jensimmons: If we just have one origin per file, we don't have to solve that problem. Instead, the ilness can be on solving this outside those CSS files <myles> jensimmons: What fantasai said about needing CSS syntax for all features is interesting though. <fantasai> TabAtkins, more specifically, I think a project should be able to control the stuff inside it, and the outer scope can't rearrange. But outer scope re-arranges everything it imports, with each direct import treated as atomic even though it may contain sub-origins <tantek> s/ilness/onus <TabAtkins> fantasai, Yes. *Possibly* with an ability for a project to project its layers into reorderable groups (like normal vs important, or reset vs actual, like fremy said), but that's probably more complexity than needed right now. <myles> jensimmons: Another thing that the frontend development world has create to create many files for keeping code organized and making it easier for multiple people to work on code, SASS has a technique that people use a lot where there's a main file where there's a file that lists other files. There's a meta file that lists the files. In a way that's what HTML is being used for. Perhaps we add osmething to CSS which is a manifest which describes other files <myles> jensimmons: The other thing is if we were to say no, you have to have separate files, and there is no concatenation, is everyone using HTTP/2? Because that's the reason build systems concatenate things to lower the number of HTTP requests. Not great for performance. Unless HTTP/2 takes over the world <myles> jensimmons: florian said what I was going to say. If nesting is allowed, does the nesting get flattened adn then delivered, or does it stay unflattened somehow. This is where the complexity for the brain-space in authors could get out of control. We all agree we want to avoid <Rossen_> q? <myles> jensimmons: We don't want a system wehre a team fo 40 people can't keep track of how things work because of nesting inside nesting inside nesting etc. <myles> Rossen: there's lots of progress on this issue <myles> miriam: I think we've covered a lot of the issues. I'd love if one or two people could help me flush them out from here. <myles> rossen: the one thing we need as a set of next steps is to write down some of the guiding principles that were used here, and use them as a guiding mechanism for designing next steps. Whether we're talking about how the origins or defined assuming they already work somehow and once this is done we can find how and where they interleave and interact <myles> astearns: It might be useful to have a regular meeting on custom origins for a while. One / month, once / fortnight <myles> astearns: The only topic is what the current issues are for this. So we can make some quicker progress. <myles> Rossen: sounds good. Like the "grid task force". <myles> 5 minute break! Then jump into the world of ruby! |
I also think there's something to be said for "nested" origins being simpler for authors – because of the potential for modularity. The ability to flatten origins when I consume them, means I don't need to maintain the full picture in my mind at once. |
From the discussion, today, I think it's worth listing out our use cases / horror cases & work out requirements from them. Some examples (which we can debate about how important they are): Use case: Use case: Use case: Horror case: |
I'd add one more use case: polyfilling for browsers that don't yet support cascade layers. It seems to me that it would suffice to define exactly one new layer, and define it via an
The second layer would be just the usual CSS layer for a developer's style sheet. Referring back to @AmeliaBR's use cases:
|
Our previous discussions on this suggested that we needed more than a single additional layer, but that we could generally solve each individual use-case with three built-in layers - "defaults", "normal", and "override" (along with their inverted !important versions). I think we also definitely still need to address the "scoping" of 3rd-party stuff, so they can use layers for their own purposes without necessarily having an effect on your layer usage. The important thing about providing predefined layers is that it allows us to reasonably do non-scoped stuff without complicated aliasing mechanisms (which custom names/ordering would require). |
The CSS Working Group just discussed The full IRC log of that discussion<dael> Topic: [css-cascade] What are the proper "levels" for managing Cascade Layers?<dael> github: https://github.com//issues/4969 <dael> chrishtr: I can summarize the latest update <TabAtkins> q+ <dael> chrishtr: Discussed at previous F2F. I prop we start with simplest set of layers; 2. Base between UA and regular stylesheets and then regular stylesheets. Allows simple use case where you import a widget. You can define what's important to the widget and would break without and than use those customizable. <dael> chrishtr: 3rd part dev marks what's important and can't be overwritten. Then with normal cascade if they want to override not required they put in their own rule to change. <dael> Rossen_: Allow library or component authors to provide sensible defaults and allow consumers... <dael> chrishtr: To customize properties that are appropriate to customize <Rossen_> q? <dael> chrishtr: We tried to make this polyfillable so that existing websites like nextJS could with small dev effort translate existing layers into an ordering of stylesheets on the page and the specificities that are eq. <dael> chrishtr: Then sites could use right away in build steps until browsers finish impl <dael> Rossen_: How does multiplicity here have anything additional against this? More than 2 layers? <dael> chrishtr: How would that make it harder? <dael> Rossen_: Yeah <miriam> q+ <dael> chrishtr: Maybe there isn't a good reason other than 2 is smallest number. Kind of a joke, kind of not. Good principle to find smallest solution. Also use cases I've talked to devs about seem completely solved. You have component and site and I"m not sure you have 3 people <dael> Rossen_: Reasonable. minimum and sufficient. We have lots of talk about how more layers can be used, but I buy this. <Rossen_> ack TabAtkins <dael> TabAtkins: Me chrishtr and miriam discussed and drilled pretyt heavy to predefined layers. It's important aspect. At the time we thought we needed 3, but number isn't important. Important is one of the big issues about how to make it make sense if if you you have arbitrary names and ordering you can define those reasonable <dael> TabAtkins: But as soon as you add otehr libraries with custom layers if you're scoping and interoperate so theither normals go with yoru normals custom names become very difficult. If you have 1 library you can change but with 2 libraries there are too many names. <dael> TabAtkins: It gets very complex <dael> TabAtkins: Whereas if we start with a small number of predefined and named layers it lets us solve those issues w'o extra problems. You know what default layer is for and you can import. Everyone using default will use in roughly same way <dael> TabAtkins: As long as people abide by what the layers mean you'll be able to integrate with 3rd party and they just work. <dael> TabAtkins: I think that's important aspect that needs to be considered and we should go with for v1 of custom cascade. Having a small number defined hadnles a lot <Rossen_> q? <dael> chrishtr: Collapsing layers to 1 at run time is not trivial, miriam brought up. If you don't have polyfill offline it's not easy <dael> miriam: I'm interested in finding the simpliest poss starting place. Agree a few named defined layers is good to start. <Rossen_> ack miriam <dael> miriam: A few concerns with this proposal where it's so focused on polyfill I'm not sure how it's helping. Offhand it supports use cases but doesn't do a lot toward them. Are we solving the problem or focused on polyfill. I don't know that's not sollving the problem <dael> miriam: One feels to me like it could be a good place to start. The examples rely heavily on !important and where so I'm not sure I see how polyfill is simplier without extra steps <dbaron> I thought TabAtkins said something above about an import mechanism that collapsed layers, but I didn't see it minuted, and I missed some of the detail of what he said. <TabAtkins> dbaron, being able to say "import this library's styles, but just treat all of them as living in layer X of my page (while respecting their own internal layer usage)" <dael> miriam: I also think there's a trade off when we go to predefined layers. It's that we don't get any modularization control which was another potential feature. Ability for final author to modularize by collaposing layers together and say I don't trust bootstrap to get this but can subsume it. It maybe can be handled sep but it's a trade off for same layers <Rossen_> q? <dael> fantasai: +1 to miriam <Rossen_> ack fantasai <dael> fantasai: I understand desire to make this polyfillable but I think we have not explored what it would look like concretely and take what miriam prop in Jan and make that real. <dael> fantasai: What she prop is a really powerful system that adds abilities to cascade and authors would find powerful. Simplify to 2 layers is not that compelling. To try and design that would prevent us from trying to understand full picture <dael> fantasai: At this stage I'd rather explore full context miriam proposed. Then if there is a subset we want to ship first that's fine. But taking on this restrictive set I don't think gives us something to build off of to get where we want to go <dael> fantasai: Would rather explore original prop from miriam, get that concrete enough to know what it looks like and have specific issues. Shouldn't restrict to polyfillable since the whole point is platform isn't capable of what we want. <dael> chrishtr: Which use cases not satisfied <dael> fantasai: Prop is flatten out but when working with multiple systems you'll have all the problems with cascade. Point of this was encapsulate so you don't have specificity of selectors cross interacting. You lose that. If you're losing where for everything you can't control specificity of selectors. Won't have real effect of cascade layer by flattening all selectors <dael> miriam: Answering it differently it doesn't break any of them but it doesn't go the full way in aiding complexity. <emilio> q+ <dael> miriam: Something like this scaled back may be useful but I want to see in context of how it would expand. I want to see the whole system and than what a scaled back impl would look like. WHat's the potential to grow and how are we designing first impl so growth is in mind <dael> chrishtr: Where is only to support polyfills. <Rossen_> q? <dael> TabAtkins: Using where as polyfill you can do arbitrary layers. THe details of that is not important <dael> chrishtr: You can have a build tool that sticks thigns in where clause. Laying out what I thought of <dael> emilio: Most use cases I read about are things conflicting inside same cascade origin. Rather than inventing new ones, sorting order in cascade is specificity and then source. WOuld it make sense to add a 3rd so it's user defined, then specificity, thank source. <dael> emilio: Multi cascade explodes when you have shadow dom. With this you don't have the problem and solve use cases. <dael> chrishtr: Would that take care of non-overridable library rules? <dael> emilio: Potentially. You can define this number is sort of like cascade origins <dael> miriam: I think difference is only if layers exist above or below shadow dom in cascade which is still open <dael> emilio: Yeah. And I think this is more efficient to impl <dael> TabAtkins: I think for spec complexity we'd have to impl this as new specificity. <miriam> +1 <dael> emilio: Okay, that makes me less scared about perf implications <Rossen_> q? <emilio> ack emilio <Rossen_> ack emilio <Rossen_> ack dbaron <dael> dbaron: I was trying to think about something TabAtkins said about an import mech that imports something with stuff from both layers and than collapses <dael> dbaron: 2 ways to do that and not sure which talking about. One is pretend the layer never existed. Other is sort them in there as though layers and then collapse to one layer <dael> dbaron: I guess that doesn't work. Now that I said it out loud. <dael> TabAtkins: My intention was there is a strong case to not interleave but still let the library use layers for code org. Sort the rules specificity wise and then collapse to one layer to interact with yoru pages <dael> dbaron: Not sure how that works if you interleave with non-collapsed rules <dael> TabAtkins: I'm thinking it just lives on a layer. Ther ineroperate with other rules in that layer <dael> dbaron: So it breaks some author assumptions who put in 2 layers about wat overrides what? <dael> TabAtkins: Shouldn't. Their layers respected in their own thing. <dael> dbaron: That's what I was starting to think but convinced myself it made more sense <Rossen_> q? <dael> TabAtkins: Definitely need more thought time on this topic. <dbaron> s/more sense/no sense/ <dael> Rossen_: Going back to direction...2-layer approach vs continue to explore full set of options from jen and miriam. WHere are we swaying? <dael> Rossen_: One thing I didn't grasp is would hte 2 layer prevent us from expanding later down the path to get full set of layers? <dael> TabAtkins: I don't think it does. Particularly when we do it with a naming structure and we can distinguish between these defaults. <dael> Rossen_: Same mental model as css properties then variables then custom properties? So we have properties now we're adding variables and we'll then expand <dael> TabAtkins: yes <Rossen_> ack fantasai <dael> fantasai: I'm not convinced this requires naming. I would like to see us try and draft something more concrete. <dael> fantasai: If we have multi prop that's interesting, but I haven't seen one that represents what we discussed in Jan and until we have one I don't think locking down is a good idea <dael> TabAtkins: fantasai and I intend to put out a draft spec and will have miriam in that <dael> fantasai: florian has also drafted ideas so we can talk together and see if we align or we come up with multiple proposals <dbaron> I'm definitely interested in seeing more alternatives. <dael> Rossen_: Last time we discussed we agreed to have a smaller taskforce. Is that forming? <dael> many: yes <dael> Rossen_: fantasai are you willing to take this on and get it organized? <dael> chrishtr: miriam would you prefer to do it or have fantasai do it? <dael> miriam: Fine if you take that <dael> fantasai: miriam time zone? <dael> miriam: Mountain <dael> astearns: So I think we're done with this issue |
I keep doing this in my head, but per Emilio's concern about doing layers as specificity vs origins, I don't actually quite mean this. ^_^ (That is, I'm pretty sure layers need to be done as a new specificity value, stronger than all the existing ones.) It might be useful to have layers invert their ordering in !important, tho, so "base" styles can put themselves in the highest position when necessary. |
The current Cascade 5 draft allows nesting layers, using an
|
Moved the remaining question into a new issue, and closing this general question as resolved by the spec. |
This is in relation to #4470 custom-origin proposal, and Cascade 5.
There are several (non-exclusive) ways the feature could be implemented and managed by authors, at different levels. (Any new syntax here is for demo purposes, not a final proposal):
<link>
&<style>
)@import
)@origin
)!<origin>
)If custom origins are managed only by the html file:
I think this could cover the main use-cases (
Reset < Design System < Overrides
,Reset < Defaults < Patterns < Layouts < Components
,CMS Core < CMS Extend < Base Theme < Site Styles
,Old Styles < New Styles
). Those layers can often be divided cleanly into files.One downside might be a performance hit from multiple links? It also ignores inline style attributes, which would either need a default relationship to custom origins, or a unique syntax.
Options 2-4, would support the same use-cases without enforcing any particular code organization or file-splitting. Overrides could be written directly next to the code they override. But the distributed approach makes things more complicated:
If custom origins are defined anywhere and shared globally, then an author would have to keep all possible origins in mind while working. If a library like Bootstrap decides to use 6 origins internally, you’ll need an origin-7 in order to override that. That doesn't feel manageable, and is where most concerns have been raised (the "
z-index
wars" comparison).On the other hand, it might be resolved by allowing custom origins to be nested, so that the final link/import would retain full control over stacking. You could import hypothetical
bootstrap.css
with a file-level origin of 0, and any internal origin of 6 becomes 0.6 in context. This avoids escalation across CSS documents.This also opens up some new use-cases – similar to the proposed
!default
– for defining component properties that should accept values from a lower-origin (e.g. "theme"), or using custom origins inside a style attribute. (These use-cases are currently handled by custom properties in Shadow DOM and elsewhere).ToDo:
The text was updated successfully, but these errors were encountered: