Skip to content
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

Support for CSS layers #1117

Open
viridia opened this issue Nov 14, 2022 · 1 comment
Open

Support for CSS layers #1117

viridia opened this issue Nov 14, 2022 · 1 comment

Comments

@viridia
Copy link

viridia commented Nov 14, 2022

One of the problems with CSS-in-JS frameworks generally is that it's hard to control the cascade order. This often results in styles overriding each other in undesirable ways, for example your 'hover' style taking a higher precedence than your 'disabled' style. There are various workarounds, such as adding extra && to up the specificity, but these are just hacks.

The solution is to support CSS layers. The way I envision it, the list of layers would be passed into the createStitches() constructor. It would take a list of names in camel case, for example:

createStitches({
  layers: ['uiBase', 'uiVariants', 'uiStates'],
  ... etc.
)}

Once defined, the layers can then be used in any call to css():

const myCss = css({
  uiBase: {
    borderColor: 'red',
  },

  uiStates: {
    '&:hover': {
      borderColor: 'blue',
    }
  }

The CSS properties within the layers can use any of the syntax that is normally allowed in the css() call. From an implementation standpoint, this means that they layer names are merged in with the CSS argument keys just like variants and such. It is the responsibility of the caller to ensure that layer names don't conflict with any CSS property names.

CSS properties not wrapped in layers will work just as they do today. Because of the way CSS layers work, classes not wrapped in a layer have a higher precedence than any explicitly-named layer, which is what we want.

When the stylesheet is generated, layers would have the following effects:

  • The layer names would be converted to kebab-case.
  • The stylesheet would include a definition of layer order:
@layer ui-base, ui-variants, ui-states;
  • Class definitions would be output multiple times, once for the default layer (if there are any non-layered props) and once for each layer mentioned. All layers would be merged so that the @layer name would only appear once in the output.
.xx-1234 {
  border-color: blue;
}

.xx-4567 {
  border-color: red;
}

@layer ui-base {
  .xx-1234 {
    background-color: #ff0000;
  }

  .xx-4567 {
    background-color: #ff0000;
  }
}

@layer ui-states {
  .xx-1234:hover {
    filter: brightness(1.1);
  }

  .xx-4567[disabled] {
    opacity: 0.5;
  }
}

Note: while it is possible to use layers currently by simply treating them as media queries, it is not very efficient, because the @layer definition is treated like a selector expression, and is output separately for each individual CSS class that uses a layer - in other words, the layers are not merged, so the @layer is repeated many times.

@iduuck
Copy link

iduuck commented Mar 4, 2023

Never heard of those layers before, but interesting concept. However, I think stitches will not get any new features in the meantime (see #1144)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants