🔥

vuejs/core に css nesting した scoped style にて :deep() を使ったときの不具合を報告した話

に公開

vuejs に scoped style というものがあります。

https://ja.vuejs.org/api/sfc-css-features

それは コンポーネント内に 一意の属性を付けて周りスタイルをそこに閉じ込めるものです。

具体的には

<style scoped>
.hoge {
    color:red;
}
</style>

と書くことで

<style>
[identity].hoge {
    color: red;
}
</style>

の様な変換がされます。
ただ、上記 の変換ルールに不備があります。
具体的には css nesting と :deep() (::v-deep()) を併用した時に問題となります。

https://developer.mozilla.org/ja/docs/Web/CSS/CSS_nesting/Using_CSS_nesting

https://ja.vuejs.org/api/sfc-css-features#deep-selectors

<style scoped>
.hoge {
    :deep(.fuga) {
        color:red;
    }
}
</style>

これだと下記の様なスタイルが生成されます。

<style>
.hoge {
    [identity] .fuga {
        color: red;
    }
}
</style>

つまり、.hoge .fuga の意が .hoge [identity] .fuga になってしまい セレクタが壊れてしまうということです。
この不具合がある状態で正しいセレクターを生成させるにはこう書く必要があります。

<style scoped>
.hoge {
    &  :deep(.fuga) {
        color:red;
    }
}
</style>

これだと下記の様な生成になります。

<style>
.hoge {
    &[identity] .fuga {
        color: red;
    }
}
</style>

つまりこれなら .hoge &[identity] .fuga となり 最終的な解釈は .hoge[identity] .fuga となりますので想定されたスタイルとなります。

でそれを vuejs/core にて issues で 報告したのが下記となります。

CSS nesting and :deep() in scoped styles not working · Issue #13159 · vuejs/core

やはり play.vuejs.org が 状態をURLに保存する構造をしているので共有が楽でよいですね。

これの対応の pull request は下記となります。

[fix(compiler-sfc): auto add nesting selector for nesting ::v-deep by edison1105 · Pull Request #13163 · vuejs/core]
(https://github.com/vuejs/core/pull/13163)

以上。

Discussion