Next.js: Disable cssnano's postcss-calc

Created on 13 Sep 2020  路  2Comments  路  Source: vercel/next.js

Bug report

next build messes up complex css calc that works as expected in next dev

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Clone https://github.com/theMosaad/tailwindcss-capsize
  2. On the dev server npm run dev the calc function works as expected https://prnt.sc/ugllip
  3. When using npm run build then npm run start it shortens the calc function from
.text-6xl::before {
    margin-top: calc(-1em * ((var(--ascent-scale) - var(--cap-height-scale) + var(--line-gap-scale) / 2) - (((var(--line-height-scale) * (var(--font-size-rem) * var(--root-font-size-px)) - (var(--line-height-rem) * var(--root-font-size-px)) - (var(--line-height-unitless) * (var(--font-size-rem) * var(--root-font-size-px))) - var(--line-height-px)) / 2) / (var(--font-size-rem) * var(--root-font-size-px))) + (.05 / (var(--font-size-rem) * var(--root-font-size-px)))));
}

to

.text-6xl::before {
    margin-top: calc(-1em*(var(--ascent-scale) - var(--cap-height-scale) + .05));
}

That's when I added the following to postcss.config.js

module.exports = {
  plugins: {
    cssnano: {
      preset: ['default', { calc: false }],
    },
  },
}

Expected behavior

Expected the full calc function when using npm run build

System information

  • OS: Windows 10
  • Version of Next.js: 9.5.3
  • Version of Node.js: 12.18.2

Additional context

I tried the same cssnano options on a gulp configuration and it disabled calc.

const gulp = require('gulp')
const postcss = require('gulp-postcss')
const cssnano = require('cssnano')

gulp.task('css', function () {
  return gulp
    .src('input.css')
    .pipe(
      postcss([
        cssnano({
          preset: ['default', { calc: false }],
        }),
      ])
    )
    .pipe(gulp.dest('dist'))
})
bug 2

Most helpful comment

A temporary workaround for those having a similar issues is using intermediate CSS variables with top level calculations only.

For me, was turning:

.text-6xl::before {
    margin-top: calc(-1em * ((var(--ascent-scale) - var(--cap-height-scale) + var(--line-gap-scale) / 2) - (((var(--line-height-scale) * (var(--font-size-rem) * var(--root-font-size-px)) - (var(--line-height-rem) * var(--root-font-size-px)) - (var(--line-height-unitless) * (var(--font-size-rem) * var(--root-font-size-px))) - var(--line-height-px)) / 2) / (var(--font-size-rem) * var(--root-font-size-px))) + (.05 / (var(--font-size-rem) * var(--root-font-size-px)))));
}

into:

.text-6xl::before {
    --line-height-normal: calc(var(--line-height-scale) * var(--font-size-px));
    --specified-line-height-offset-double:
    calc(var(--line-height-normal) - var(--line-height-px));
    --specified-line-height-offset:
    calc(var(--specified-line-height-offset-double) / 2 );
    --specified-line-height-offset-to-scale:
    calc(var(--specified-line-height-offset) / var(--font-size-px));
    --prevent-collapse-to-scale:
    calc(0.05 / var(--font-size-px));
    --line-gap-scale-half: calc(var(--line-gap-scale) / 2);
    --leading-trim-top:
    calc( var(--ascent-scale) - var(--cap-height-scale) + var(--line-gap-scale-half) - var(--specified-line-height-offset-to-scale) + var(--prevent-collapse-to-scale) );
    margin-top: calc(-1em * var(--leading-trim-top));
}

All 2 comments

A temporary workaround for those having a similar issues is using intermediate CSS variables with top level calculations only.

For me, was turning:

.text-6xl::before {
    margin-top: calc(-1em * ((var(--ascent-scale) - var(--cap-height-scale) + var(--line-gap-scale) / 2) - (((var(--line-height-scale) * (var(--font-size-rem) * var(--root-font-size-px)) - (var(--line-height-rem) * var(--root-font-size-px)) - (var(--line-height-unitless) * (var(--font-size-rem) * var(--root-font-size-px))) - var(--line-height-px)) / 2) / (var(--font-size-rem) * var(--root-font-size-px))) + (.05 / (var(--font-size-rem) * var(--root-font-size-px)))));
}

into:

.text-6xl::before {
    --line-height-normal: calc(var(--line-height-scale) * var(--font-size-px));
    --specified-line-height-offset-double:
    calc(var(--line-height-normal) - var(--line-height-px));
    --specified-line-height-offset:
    calc(var(--specified-line-height-offset-double) / 2 );
    --specified-line-height-offset-to-scale:
    calc(var(--specified-line-height-offset) / var(--font-size-px));
    --prevent-collapse-to-scale:
    calc(0.05 / var(--font-size-px));
    --line-gap-scale-half: calc(var(--line-gap-scale) / 2);
    --leading-trim-top:
    calc( var(--ascent-scale) - var(--cap-height-scale) + var(--line-gap-scale-half) - var(--specified-line-height-offset-to-scale) + var(--prevent-collapse-to-scale) );
    margin-top: calc(-1em * var(--leading-trim-top));
}

We're having this issue as well (as expected since it's a parser issue), but in a way that can't be worked around with multiple declarations: we're generating a deep calc value (for a responsive type system) in a SASS @function which means its usage should only return a single value.

Until we can configure cssnano's config to unblock this, would it be possible to override @Timer's https://github.com/Timer/cssnano-preset-simple using Yarn resolutions?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lixiaoyan picture lixiaoyan  路  3Comments

rauchg picture rauchg  路  3Comments

formula349 picture formula349  路  3Comments

swrdfish picture swrdfish  路  3Comments

havefive picture havefive  路  3Comments