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

ParserError when dividing a CSS variable by a negative number #10880

Open
Flonk opened this issue Apr 25, 2021 · 9 comments
Open

ParserError when dividing a CSS variable by a negative number #10880

Flonk opened this issue Apr 25, 2021 · 9 comments

Comments

@Flonk
Copy link

Flonk commented Apr 25, 2021

Describe the bug

Dividing a CSS variable by a negative number yields a ParserError during production builds. Live preview works ok.

Which terms did you search for in User Guide?

ParserError, CSS variables

Environment

Environment Info:

  current version of create-react-app: 4.0.3
  running from <snip>\create-react-app

  System:
    OS: Windows 10 10.0.19042
    CPU: (16) x64 Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz
  Binaries:
    Node: 15.5.1 - C:\Program Files\nodejs\node.EXE
    Yarn: Not Found
    npm: 7.9.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: Not Found
    Edge: Spartan (44.19041.906.0), Chromium (90.0.818.46)
    Internet Explorer: 11.0.19041.1
  npmPackages:
    react: ^17.0.2 => 17.0.2
    react-dom: ^17.0.2 => 17.0.2
    react-scripts: 4.0.3 => 4.0.3
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

  1. Create a fresh react app with npx create-react-app --template typescript
  2. Add the following css to App.css:
.App-logo {
  --size: -10px;
  width: calc(var(--size)/-2);
}
  1. run npm run build

Expected behavior

The build should compile successfully, since live preview works as expected.

Actual behavior

PS C:\<snip>\cra> npm run build

> cra@0.1.0 build
> react-scripts build

Creating an optimized production build...
Failed to compile.

./src/App.css
ParserError: Syntax Error at line: 1, column 18

Etc

If either var(--size) is replaced by some constant, or the expression is rewritten as calc(-1/2 * var(--size)), the problem disappears.

@totymedli
Copy link

totymedli commented Aug 25, 2021

Problem and Error

I can confirm this. The following rules will cause an error during npm run build (react-scripts build)

--bs-gutter-y:0;
margin-top:calc(var(--bs-gutter-y)*-1)

The error is:

ParserError: Syntax Error at line: 1, column 25

BTW the rule is not in line 1 column 25, so it is totally misleading.

Solutions

  • One solution is to change the operands just like OP suggested: margin-top:calc(-1*var(--bs-gutter-y))
  • Alternatively, add a space before the -: margin-top:calc(var(--bs-gutter-y)* -1)

This code is from Bootstrap 5.0.2 which has the spaces (even in the minified version) so my assumption is that somewhere, the script minifies it again and removes the spaces. This could explain why it works in dev mode, where presumably there is no minification.

Also, check out this related Stack Overflow question.

@fewlme
Copy link

fewlme commented Sep 20, 2021

Thanks for the solutions @totymedli but where can you change those ?
I'm importing bootstrap from my main scss file (so I can change all the default variables and create my own theme, etc) like this
@import "~bootstrap/scss/bootstrap";
No clue where to change the -1 fix... I looked in all the @import from the main bootstrap.scss file...
Thanks for your help

@yudielcurbelo
Copy link

I'm having something similar.

This does not work.
margin-top: calc(var(--#{$variable-prefix}gutter-y) * -1);

But this works.
margin-top: calc(var(--#{$variable-prefix}gutter-y) * (-1));

Also using Bootstrap.

@fewlme
Copy link

fewlme commented Sep 21, 2021

Found the fix :
In boostrap/scss/mixins/_grid.scss

Change :

  margin-top: calc(var(--#{$variable-prefix}gutter-y) * -1); // stylelint-disable-line function-disallowed-list
  margin-right: calc(var(--#{$variable-prefix}gutter-x) * -.5); // stylelint-disable-line function-disallowed-list
  margin-left: calc(var(--#{$variable-prefix}gutter-x) * -.5); // stylelint-disable-line function-disallowed-list

with

  margin-top: calc(-1*var(--#{$variable-prefix}gutter-y)); // stylelint-disable-line function-disallowed-list
  margin-right: calc(-.5*var(--#{$variable-prefix}gutter-x)); // stylelint-disable-line function-disallowed-list
  margin-left: calc(-.5*var(--#{$variable-prefix}gutter-x)); // stylelint-disable-line function-disallowed-list

@totymedli
Copy link

@fewlme You are editing a 3rd party library. That works only if you add the dependency directly to your project. If it is inside node_modules you can't do this. So this is more of a workaround.

@fewlme
Copy link

fewlme commented Sep 21, 2021

True @totymedli, it's more a hack until I npm update the hell out of it :) but I can now build my react app without the parserError

@nex3
Copy link

nex3 commented Dec 2, 2021

Sass recently added additional features for calc() which includes more aggressively minifying whitespace in calc() expressions. Note that the problematic expression calc(var(--bs-gutter-y)*-1) is valid CSS. To quote Values and Units Level 4:

(The * and / operators can be used without white space around them.)

It seems like some other tool is parsing Sass's output and choking on this valid CSS, which is likely a bug in that tool.

@tcchau
Copy link

tcchau commented Jan 4, 2022

Just adding another workaround: moving the literal values to the front of the expression seems to avoid any problems caused by minification or other processing, e.g.

calc( -1 * var(--bs-gutter-y))

Merely adding whitespace in front of the minus sign in the literals was not sufficient for me.

For reference, I am using react-scripts 4.0.3, sass 1.45.2, and CSS modules.

I found the idea for this workaround from: https://issueexplorer.com/issue/react-bootstrap/react-bootstrap/6039

@kclay
Copy link

kclay commented Jan 26, 2022

This can be resolved if using bootstrap 5.1.0 with the following patch

bootstrap+5.1.0.patch

put this in patches/bootstrap+5.1.0.patch and adjust your package.json to have the following

{
   "scripts":{
      "postinstall":"patch-package"
   },
   "devDependencies":{
      "patch-package":"^6.4.7"
   }
}

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

No branches or pull requests

7 participants