Early notes about Cascade Layers

This may be of limited relevance since we have since moved further, but I have some early notes that I had shared with fantasai, Mia and Tab about Cascade layers. Instead of just letting them disappear, it seemed that sending them here would be a reasonable way to share and preserve, in case we ever wanted/needed to look what happened in early iterations. I don't have an exact date, but it should date to some time within May–July 2020.


> FLORIAN'S NOTES ON CASCADE LAYERS PROPOSAL
> 
> Today we have this:
> Figure A
> ! UA
> ! USER
> ! AUTHOR
>  ~ANIMATIONS~
>  AUTHOR
>  USER
>  UA
> 
> A flat view of custom origins get this:
> Figure B
> ! UA
> ! USER
> ! style attr ? option A (yes from Tab + fantasai)
> ! a3
> ! a2
> ! style attr ? option B
> ! unlayered author a1
>  ~ANIMATIONS~
>  style attr
>  unlayered author a1
>  a2
>  a3
>  USER
>  UA
> 
> The ability to create origin subtrees would suggest something like that:
> 
> Figure C
> ! UA
> ! USER
> ! a3
> ! a2
> ! a1
>  ~ANIMATIONS~
>  a1
>  a2
> !  a2.1
> !  a2.2
>   a2.2
>   a2.1
>  a1
>  USER
>  UA
> 
> I don't think we need that, because if you need that, you're just doing it within layers you control, and you can just create more of them, without invoking !important.
> 
> I think we need encapsulation though, which would look like this:
> Figure D
> ! UA
> ! USER
> ! a3
> !   a2.2
> !   a2.1
> ! a2
> ! a1
>  ~ANIMATIONS~
>  a1
>  a2
>   a2.1
>   a2.2
>  a3
>  USER
>  UA
> 
> Looking at an example with concrete names, that'd be something like this
> Figure E
> ! UA
> ! USER
> ! css-reset
> !   bootstrap.base
> !   boostrap.components
> ! bootstrap
> ! AUTHOR
>  ~animations~
>  AUTHOR
>  bootstrap
>    bootstrap.components
>    bootstrap.base
>  css-reset
>  USER
>  UA
> 
> Let's make this interesting by assuming that while boostrap is custom-layer aware, the reset is not, but we still want to put it in a layer.
> 
> Elika's syntax:
> author.css
>    @layer url(css-reset.css);
>    @layer url(bootstrap.css);
> 
>    other stuff here
> 
> bootstrap.css
>    @layer url(bootstrap-base.css);
>    @layer url(bootstrap-component.css);
> 
> Note: @layer can be expanded in-place using a block, e.g. @layer { ... stuff here ... } for an equivalent effect.
> 
> 
> This is quite possibly enough to solve the whole thing. However, it could be useful to be able to name layers in order to mix rules from differnet sources into the same layer. Here's an expansion of the above syntax that does that.
> 
> author.css
>    /* layers sort in first-encountered order by default */
>    @layer reset url(css-reset.css);
>    @layer bootstrap url(bootstrap.css);
> 
>    other stuff here overrides anything in the sub-layers
> 
> The example above assumes that bootstrap (and the reset) are not defined with layers, and that the layers are created at the point of use.
> 
> But they could also be built in:
> 
> bootstrap.css
> 
>    @layer base {
>        color stuff
>    }
> 
>    @layer components {
>        color stuff
>    }
> 
>    @layer base {
>        font stuff
>    }
> 
>    @layer components {
>        font stuff
>    }
> 
> 
> Note: Can hook into bootstrap's encapsulated layers explicitly by using @layer boostrap base { ... } or @layer bootstrap.base { ... } ?
> 
> Question: I don't think there's a problem with Shadow DOM or Scope. Is there?
> 
> 
> I believe that this proposal nicely addresses all of the use cases discussed, except maybe one, which it does address, but not as nicely:
> 
> Tab had discussed that it would be nice for old side maintenance to be able to slot all the existing styles into a "legacy" layer, and then have any/all new style in a higher priority layer, so that when you want to make a tweak, you don't need to worry about the specificity of any legacy stuff.
> 
> This proposal has two weaknesses with regards to that:
> * you cannot create a new layer that's higher priority than the unqualified author layer, so you can only do Tab's trick if you have enough access to the legacy code to change how the legacy styles are imported, and put them in a separate layer.
> * Even if you can do that, if the old styles use !important, and you want your new styles (at least their !important, but maybe even their normal rules) to win over that, you cannot do that directly. You can do the equivalent if you have some kind of css transpiler which would convert the old style so as to put normal rules in one layer, and !important rules into normal rules in another layer. Then new styles can win over that. This is a purely mechanical transformation that can be done server side, but if it needs to get syntax-error handling right, it may not be trivial to write.
> 
> So Tab's maintenance use case is kind of solved, but only if authors have write access to the legacy styles, and are willing to convert them into @layer syntax.
> 
> A final question is where does the style attribute fit in all this. In level 2 it was described through specificity and belonged to the normal author layer. In level 3, it is described through the scoping mechanism, but that's not really implemented anywhere, so maybe it's time to re-explain it some other way.
> 
> The interesting questions that this raises are:
>    * How does it's !important interact with the other layers and their !important?
>    * If one day it becomes possible to put @rules in style attribute, presumably you could put @layer in there. Would the result of doing that make sense in whatever model we pick?
> 
> Seems to me that if we drop scope, reverting to defining style attr through specificity would be fine.

Received on Tuesday, 27 July 2021 10:10:42 UTC