近々リリース予定の Sass 3.4.0 では、& が SassScript で使えるようになるほか、セレクター関連の関数が大きく充実する。SassMeister ではすでに使えるので いくつか試してみた けど、セレクターを置換するselector-replace() 関数がかなり便利そう。

使用例としてはまず、ネストしたセレクターで、ルートと直近のセレクターの間に別のセレクターを挿入する、というのが考えられる。

.outer {
    color: red;

    .inner {
        color: green;

        @at-root {
            #{ selector-replace(&, '.outer', '.outer .foo') } {
                color: blue;
            }
        }
    }
}

& で親セレクター .outer .inner を参照し、そのうち .outer.outer .foo に置換することで、親セレクターの「間」に新たなセレクターを割り込ませるようなかたちになる。

.outer {
    color: red;
}
.outer .inner {
    color: green;
}
.outer .foo .inner {
    color: blue;
}

もうひとつ、汎用的なクラス・セレクターを定義したブロックの中で、要素タイプによる絞り込みができる。

.bar {
    .button {
        border: 1px solid;

        @at-root {
            #{ selector-replace(&, ".button", "a.button") } {
                text-decoration: none;
            }
        }
    }
}

.button という要素を問わないセレクターを定義し、その中で要素タイプが a だった場合に絞り込んだスタイルを書ける。

.bar .button {
    border: 1px solid;
}
.bar a.button {
    text-decoration: none;
}

ぱっと思いついたのはこんなところ。どちらの例も、今までだとルートから書き直す必要があったので、けっこう便利になる気がする。

ただ、まだ検証しきれてないけど、単純な置換ではなく @extend と同様のロジックらしく、直感に反する結果になることもある。最初の例で言うと、selector-replace(&, '.outer', '.outer .foo') ではなく selector-replace(&, '.inner', '.foo .inner') とすると、以下の出力になる。

.outer .foo .inner,
.foo .outer .inner {
    color: blue;
}

@extend 同様、ちょっと理解しづらいので、気をつけないとすぐ複雑になると思う。

@at-root はどうやって使えばいいのかいまいちわからなかったけど、これでようやく活用できそう。