SassでBEMを利用して変数名を付けようとして、今までハイフンのみでどうにかしていた変数名を書き換えていた時に気づいたんだけど、Sassの変数名ではハイフン(-)とアンダースコア(_)が同一視される。バグだと思ってIssue立てたら、3.0.0でSCSS記法を追加した時に入れた仕様だという返事だった。

-_が同一視されるということはどういうことかというと、以下の変数はすべて同じとみなされるということで、すべての変数の値は最後に定義した変数の値になる。

$foo--bar: "foo--bar";
$foo-_bar: "foo-_bar";
$foo_-bar: "foo_-bar";
$foo__bar: "foo__bar";

.test-foo--bar {
  content: $foo--bar;
}

.test-foo-_bar {
  content: $foo-_bar;
}

.test-foo_-bar {
  content: $foo_-bar;
}

.test-foo__bar {
  content: $foo__bar;
}

コンパイルすると以下のように全て"foo__bar"になる。

.test-foo--bar {
  content: "foo__bar"; }

.test-foo-_bar {
  content: "foo__bar"; }

.test-foo_-bar {
  content: "foo__bar"; }

.test-foo__bar {
  content: "foo__bar"; }

またエラーや警告も出ないので、間違えて参照してもエラーに気付くのは難しい。例えばBEMのモディファイアの区切りを--にしていたとして、参照する時に間違えて__で参照しても運良くコンパイルされる。

$menu__item: #69c;
$menu__item--current: #369;

.menu__item {
  color: $menu__item;

  &.current {
    color: $menu__item__current;
  }
}

後方互換性のため、わざとこうしたらしい。余程のことがないとこの後方互換性が捨てられることはなさそうなので、かなり気をつけた方が良い。パッと見は間違っているコードなのに、問題なく動くのがすごく怖い。変数名でBEMを使おうとするとわりと致命的な感じあるけど、そこはIDEやエディタの補完で乗り越えるしかなさそう。もしくはアンダースコアだけを使うように宗旨変えするか。