【Sass】SCSSでネストの深い位置から途中のセレクターを置き換える方法

Sassで特定の要素がaタグではなくspanタグだった場合などのスタイルをネストの深い位置から書きたい場合ってありませんか? 僕はコーディングしていてよくあります。何言ってるか分かりづらいと思いますので例を交えながら解説します!

Sassに用意されているselector-replace関数を使用します。

selector-replace($selector, $original, $replacement)

第一引数に置換範囲のセレクター、第二引数に置換範囲内の置換したいセレクター、第三引数に置換後のセレクターを指定。

selector-replace("置換範囲", "置換範囲内の置換したいセレクター", "置換後のセレクター")

第一引数の置換範囲ってどうやって指定するの?ってなるかもしれませんが&を指定しておけば大丈夫です!
※&は親までのセレクターを取ってきます。

ネストを解除する@at-root、セレクター内で関数や変数などを使用可能にするインターポレーション#{}と組み合わせます。

.cardに.is-smallが付与されたとき.titleのスタイルを変更したい

コンパイル前

scss
.card { .title { font-size: 16px; @at-root #{selector-replace(&, ".card", ".card.is-small")} { font-size: 12px; } } }

コンパイル後

css
.card .title { font-size: 16px; } .card.is-small .title { font-size: 12px; }

これで.card.is-small付与されているスタイルができましたね!
このようにネストの深い位置からセレクターを自在に変更できるので様々な場面で活用できるかと思います。

上記の方法だと記述が長くなってしまい可読性が悪くなってしまうのでmixin化してシンプルにしようと思います。

scss
@mixin replace ($original, $replacement) { @at-root #{selector-replace(&, $original, $replacement)} { @content } }

mixin化したファイルは_replace.scssなどにしてimportするといいと思います。

mixinの使い方

scss
@include("置換したいセレクター", "置換後のセレクター") { //スタイルを記述 }

コンパイル前

scss
.card { .title { font-size: 16px; @include replace(".card", ".card.is-small") { font-size: 12px; } } }

コンパイル後

css
.card .title { font-size: 16px; } .card.is-small .title { font-size: 12px; }

結果はmixin化前と同じですね!
記述が短くなり引数も2つ指定するだけでよくなりシンプルになりました!

ネストされたセレクターの中から特定のセレクターの状態を変更するmixin

個人的にこの手法はよく使われているものだと思っています。
今回紹介した例以外にも、hover時の効果などにも使えますので、まだ使っていない方はぜひ使ってみて下さい!すごく便利ですので!