Problem: Composition and the Cascade
CSS Modules lets us extend classes using the composes declaration. When extending multiple classes, CSS Modules requires multiple composes declarations. Here is an example of what that CSS looks like:
.some-call-to-action {
composes: link from 'link-styles.module.css';
composes: button from 'button-styles.module.css';
}
The issue is that this practice of writing multiple composes declarations defies CSS Cascade (the "C" in "CSS"). Therefore, using multiple composes declarations becomes a non-preferable practice.
Only CSS declarations, that is property/value pairs, participate in the cascade.
— https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade
In CSS, properties overwrite each other, and they do not combine with each other. Here is an example of the cascade:
/* global.css (earlier in order) */
li {
margin-left: 10px;
}
/* project.css (later in order) */
li {
margin-left: 0; /* This is a reset of `margin-left` */
}
Note: That example is used in MDN’s introduction to the CSS Cascade.
Authors may also rely on this cascade to manage browser fallbacks (e.g. .layout { display: block; display: grid }).
Even the singular example from this project’s documentation of composition relies on this expectation.
Solution: Composition At-Rule
Please consider supporting a @composes at-rule, which would be functionally identical to the current composes declaration. This would allow authors to utilize composition while still respecting the expectations inherit to CSS.
Here is an example of what that CSS would looks like, mirroring the opening example:
.some-call-to-action {
@composes link from 'link-styles.module.css';
@composes button from 'button-styles.module.css';
}
Additional unintentional benefits include:
Problem: Composition and the Cascade
CSS Modules lets us extend classes using the
composesdeclaration. When extending multiple classes, CSS Modules requires multiplecomposesdeclarations. Here is an example of what that CSS looks like:The issue is that this practice of writing multiple
composesdeclarations defies CSS Cascade (the "C" in "CSS"). Therefore, using multiplecomposesdeclarations becomes a non-preferable practice.In CSS, properties overwrite each other, and they do not combine with each other. Here is an example of the cascade:
Note: That example is used in MDN’s introduction to the CSS Cascade.
Authors may also rely on this cascade to manage browser fallbacks (e.g.
.layout { display: block; display: grid }).Even the singular example from this project’s documentation of composition relies on this expectation.
Solution: Composition At-Rule
Please consider supporting a
@composesat-rule, which would be functionally identical to the currentcomposesdeclaration. This would allow authors to utilize composition while still respecting the expectations inherit to CSS.Here is an example of what that CSS would looks like, mirroring the opening example:
Additional unintentional benefits include:
declaration-block-no-duplicate-propertieswhen using multiplecomposesdeclarations.declaration-empty-line-beforewhen separatingcomposesfrom other declarations with an empty line.stylelint-orderwhen not separatingcomposesfrom other declarations with an empty line.