w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.44k stars 656 forks source link

[css-syntax] keeping the indent level under control in modern CSS with `@layer`, `@scope`, nesting, ... #8912

Open romainmenke opened 1 year ago

romainmenke commented 1 year ago

Example :

@layer components {
    @scope (.my-component) to (.child-component-slot > *) {
        .my-component {
            color: cyan;
            padding: 0.5rem;

            &:hover {
                color: blue;
            }

            @media (min-width: 768px) {
                padding: 1rem;
            }
        }
    }
}

This is starting to look a bit like the callback hell from JS :

getBeef("foo", (rawBeef) => {
    sliceBeef(rawBeef, (slicedBeef) => {
        cookBeef(slicedBeef, (cookedBeef) => {
            serveBeef(cookedBeef, (servedBeef) => {
                console.log(servedBeef);
            });
        });
    });
});

Some of this can be externalized by adding bits of it to @import :

@import "my-component.css" layer(components);

But this isn't always possible or good practice for maintainable code. Often the reason for wrapping code in an at-rule is tightly coupled with the code that is wrapped.


Using nesting is a choice and authors can choose not to nest.


@when does not help here because it wasn't designed for @layer, @scope, @container, ... Personally I don't think @when should be shipped at all because it doesn't solve the issue fully. Maybe I am wrong here and @when could be used for all at rules?


The underlying issue is that at-rules can only be "combined" or "stacked" by nesting them. With the introduction of new at-rules and nested CSS source code will only become more heavily nested and less readable.

I don't have a concreet proposal for a syntax that could help here. I do however think it is something that should be explored.

rthrejheytjyrtj545 commented 1 year ago

šŸ§

// no-spaghetti.css

@rules
{  @layer (components)
;  @scope (.my-component)
;  @boundary (.child-component-slot > *)
;  @selectors (.my-component)
;  @declarations
   {  color : cyan
   ;  padding : .5rem
}  @nest 
   {  @selectors (&:hover)
   ;  @declarations
      {  color : blue
}} @nest 
   {  @media (min-width: 768px)
   ;  @declarations
      {  padding : 1rem
}}}

šŸ¤”šŸ¤”šŸ¤”

/*\-------+
 # WHATSS #
 +-------\*/

@rules --component {
   @layer (components);
   @scope (.my-component);
   @boundary (.child-component-slot > *);
   @selectors (.my-component);
   @declarations --component;
   @nest --component-hover;
   @nest --component-response}

@declarations --component {
   @properties
      (color),
      (padding);
   @values
      (cyan),
      (.5rem)}

@nest --component-hover {
   @selectors (&:hover);
   @declarations --component-hover}

@declarations --component-hover {
   @properties (color);
   @values (blue)}

@nest --component-response {
   @media (min-width: 768px);
   @declarations --component-response}

@declarations --component-response {
   @properties (padding);
   @values (1rem)}