Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

@extend produces incorrect CSS when :nth-child(n+4) is present #2995

Open
ericwong3 opened this issue Oct 19, 2020 · 0 comments
Open

@extend produces incorrect CSS when :nth-child(n+4) is present #2995

ericwong3 opened this issue Oct 19, 2020 · 0 comments

Comments

@ericwong3
Copy link

ericwong3 commented Oct 19, 2020

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:

  • @extend is very likely the culprit, if I remove the .x {} block and change %ie-grid to .ie-grid, everything renders as normal.
  • If I just change %ie-grid to .ie-grid and update the @extend %ie-grid to @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):
my-project@1.0.0 C:\Users\eric_\Desktop\my-project
`-- gulp-sass@4.1.0
  `-- node-sass@4.14.1
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant