@extend produces incorrect CSS when :nth-child(n+4) is present
Problem
(I know the template says compilation error should go and open issue in libsass, but this problem is only happening in node-sass, and does not occur in sassmeister even if libsass is selected as the compiler, so I believe the issue lies in node-sass)
The problem apparently has to do with :nth-child, @extend and the magic number n+4 (huh but yes)
Following is the code that will result in the wrong result. For context, this is sort of a polyfill for CSS grid on IE that simulates column gap, row gap, and cell auto-placement. Column gap is done with empty column, row gap with cell's margin-top, and cell placement with @for loop. (There is a more minimal example below)
$grid-gutter-width: 40px;
%ie-grid {
display: -ms-grid;
-ms-grid-columns: 1fr $grid-gutter-width 1fr $grid-gutter-width 1fr;
// simulate row-gap on IE
> *:nth-child(n + 4) {
margin-top: $grid-gutter-width;
}
@for $i from 1 through 99 {
$row: floor( ($i + 2) / 3); // (1,2,3) => 1 ; (4,5,6) => 2 ...
$column: $i % 3; // (1,4,7,...) => 1 ; (2,5,8,...) => 2 ; (3,6,9,...) => 3 ...
@if $column == 0 {
$column: 3;
}
> *:nth-child(#{$i}) {
-ms-grid-column: ($column - 1) * 2 + 1; // (1,2,3) => (0,1,2) => (0,2,4) => (1,3,5)
-ms-grid-row: $row;
}
}
}
.test {
@extend %ie-grid;
}
This will produce the following CSS:
.x {
display: -ms-grid;
-ms-grid-columns: 1fr 40px 1fr 40px 1fr;
}
.x > *:nth-child(n + 4) {
margin-top: 40px;
}
.x > *:nth-child(1) {
-ms-grid-column: 1;
-ms-grid-row: 1;
}
.x > *:nth-child(n + 4) { /* !!! */
-ms-grid-column: 3;
-ms-grid-row: 1;
}
.x > *:nth-child(3) {
-ms-grid-column: 5;
-ms-grid-row: 1;
}
/* .... */
As seen, :nth-child(2) is mistakenly rendered as :nth-child(n+ 4), same also happens for 25 and 44, which is replaced with n+4.
Here are some tests that I have done that give a slightest hint:
-
@extendis very likely the culprit, if I remove the.x {}block and change%ie-gridto.ie-grid, everything renders as normal. - If I just change
%ie-gridto.ie-gridand update the@extend %ie-gridto@extend .ie-grid, both of them will inherit the n+4 weirdness.
Below is a further trim down of the above example, but I am not sure if this covers the whole issue though.
%ie-grid {
> *:nth-child(n + 4) {
margin-top: 1px;
}
> *:nth-child(44) {
-ms-grid-column: 15;
-ms-grid-row: 3;
}
}
.x {
@extend %ie-grid;
}
Renders:
.ie-grid > *:nth-child(n + 4) {
margin-top: 1px;
}
.ie-grid > *:nth-child(n + 4) { /* !!! */
-ms-grid-column: 15;
-ms-grid-row: 3;
}
Environment
- NPM version (
npm -v): 6.14.5 - Node version (
node -v): v12.18.2 - Node Process (
node -p process.versions):{ node: '12.18.2', v8: '7.8.279.23-node.39', uv: '1.38.0', zlib: '1.2.11', brotli: '1.0.7', ares: '1.16.0', modules: '72', nghttp2: '1.41.0', napi: '6', llhttp: '2.0.4', http_parser: '2.9.3', openssl: '1.1.1g', cldr: '37.0', icu: '67.1', tz: '2019c', unicode: '13.0' } - Node Platform (
node -p process.platform): win32 - Node architecture (
node -p process.arch): x64 - node-sass version (
node -p "require('node-sass').info"):
node-sass 4.14.1 (Wrapper) [JavaScript]
libsass 3.5.5 (Sass Compiler) [C/C++]
- npm node-sass versions (
npm ls node-sass):
[email protected] C:\Users\eric_\Desktop\my-project
`-- [email protected]
`-- [email protected]