node-sassのmin()やmax()でIncompatible unitsエラーになるバグの対処法
- 投稿日:
- 2020-09-12
はじめに
最近node-sassを使用しているプロジェクトで、CSS関数の`min()`を使った時に、Internal Error: Incompatible units: 'px' and 'vw'.
というコンパイルエラーが出ました。
min()
はpx
やvw
などの異なる単位であっても、比較してレンダリング結果が小さい方の値を適用できるとても便利なCSS関数なのですが、node-sass(記事作成時点で最新のv4.14.1)で次のSassコードをコンパイルしようとするとエラーが出てしまいます。
.hoge {
width: min(100vw, 10px);
}
/*
Internal Error: Incompatible units: 'px' and 'vw'.
*/
そして、このエラーは`max()`でも発生します。
`Incompatible units`って何
Incompatible units
は、互換性のない単位を計算している時に発生するエラーです。例えばSassで次のような書き方をすると、Sassコンパイル時にはvw
が何pxなのか判断できないため、計算できずにコンパイルエラーになります。
.hoge {
width: #{100vw - 10px};
}
/*
Error: Incompatible units: 'px' and 'vw'.
on line 2 of stdin
>> width: #{100vw - 10px};
-----------^
*/
これはSassの仕様上正しく、Dart Sassでも発生します。
ただし、CSS関数であるmin()
やmax()
はCSS側で計算するもので、Sassのコンパイルができないと困るので解決策を探しました。
解決策
これらを解決する方法はいくつかあります。
Sassの`unquote()`を併用する
このバグはSassの開発側も認識しており、Sassの公式ドキュメントのちょっとわかりにくい箇所(右向きの三角アイコンをクリックすると出てくる)に、LibSassだとまだ未サポートなのでSassのunquote()
を一緒に使ってねと記載されていました。
unquote()
は、コンパイル時に引数の文字列をそのまま出力するための関数なので、意図しないタイミングでmin()
が実行されることを防ぎます。
.hoge {
width: unquote("min(100vw, 10px)");
}
個人的にはちょっと冗長な感じがしてあまり好きではありません。
Sassのinterpolationを使う
unquote()
を使うのとしくみとしては同じで、Sassのinterpolation(#{}
)を使ってSassに文字列と認識させることでコンパイルエラーを回避することも可能です。
.hoge {
width: #{"min(100vw, 10px)"};
}
unquote()
と同じ仕組みで短く記述できるので個人的にはこっちの方が好みです。ただし、コードを書いた人以外なぜこのように書いたのかわからないことの方が多いと思うので、コメントを記載しておいた方がよさそうです。
Dart Sassを使う
このバグはDart Sass(記事作成時点で最新のv1.26.10)ではすでに修正されているので、sassを使うことでこのエラーは出なくなります。
ただし、このエラーのためにいきなりDart Sassに移行するのはテスト工数などもかかり業務ではなかなか難しいので、Dart Sassに移行する余裕がある場合に行うのが良いかと思います。
まとめ
Incompatible units
はSassで互換性のない単位の計算をさせようとしている時に発生するエラー。- node-sass(LibSass)ではバグがあり
min()
やmax()
で異なる単位の比較をしようとするとコンパイルができない。 - いくつかの方法で解決できる。
- Sassの
unquote()
を併用する。 - interpolation(
#{""}
)で文字列としてコンパイルする。 - Dart Sassに移行する。
- Sassの
このバグに限らず、今後を考えるとDart Sassに移行してしまった方がいいですが、業務ではテストにかかる負担などを考えるとサクッと移行できるものでもないので、緊急性が高い場合はunquote()
やinterpolationを使うのが良さそうです。
そして、最近sass-diffというDart SassとNode Sassのコンパイル結果の差を確認するための簡単なWebアプリを作っているので、Sassのコンパイラの違いによる出力の違いをチェックしたい時などに是非ご活用ください。まだ使いにくいところがありますが、今後改善していきます。