calc()内の0

感覚としてcalc(1rem + 1)は明らかにダメそうだとわかるが、なんとなく通りそうに見えるcalc(1rem + 0)もダメになるということをCSSWringへのPRで知った。0ならユニットを省略できることが多いが、calc()内では別のようだ。最初良くわからなかったが、この辺りを定義しているCSS Values and Units Module Level 3仕様でもちゃんとそうなっていた。

仕様ではcalc()の内容を処理する時に、右辺と左辺の型をチェックすることを求められている。*(乗算)の場合は両辺のどちらかが数字であることが、/(除算)では右辺が数字でありかつ0ではないことが求められる。そして+(加算)と-(減算)では両辺の型が同じである<number><integer>の組み合わせであることが求められる。

問題のcalc(1em + 0)は左辺が<length>で右辺が<integer>となる。そのため両辺の型が一致せず文法違反になる。実際に各ブラウザーでもことごとく無視されるようになる。


CSSWringではプロパティーの値の中で単位を外せそうな0の長さかパーセンテージを見つけたら問答無用に削除していたため、このバグを作ってしまっていた。PRではcalc()かどうか簡単に探してスキップされるようになっており、これで問題なさそうだったため、ちょっとだけマッチ方法を変えてマージした。そういうわけでCSSWring v4.1.0では既に修正済みだ。


v4.1.0では::before:beforeに縮める機能も追加している。すべての擬似要素というわけではなく、以下の4つの擬似要素でのみ1つに縮められる。

これら以外の擬似要素でコロンを1つにすることはセレクターの仕様では許されていない。同時にこれらの擬似要素では後方互換性のために必ずコロン1つでも良いように実装することとなっているので、安全に縮めることが可能だろう。