
Vue.jsでディープセレクタを使って親コンポーネントから子コンポーネントの要素にスタイルを適用させる
Vue.jsではそれぞれの要素をコンポーネントと定義し、それらを組み合わせる形でプロジェクトが構成されているケースが多いです。そして、単一コンポーネントファイル(過去記事「Vueインスタンスで使うオプションと単一ファイルコンポーネントについて(単一ファイルコンポーネント編) 」参考)では、1つのファイルでHTMLとjavascript、CSSをまとめて記述していきます。
この時にコンポーネント内の要素に対してはCSSを適用できますが、呼び出している子コンポーネントにある要素へはそのままですとスタイルが適用されません。今回は「ディープセレクタ」を使って、親コンポーネントから子コンポーネントの要素に対してスタイルを適用させる方法をまとめていきます。
まず、一般的な親子構造のコンポーネントで、スタイルを適用させる例を見ていきます。親コンポーネント側で特定の要素に対してスタイルを指定します。そして子コンポーネント側でも同じスタイルを適用させたい要素を用意します。
【ComponentParent.vue】
これはVueコンポーネントのstyle要素にscoped属性が適用されているのが理由です。つまり、通常ではコンポーネント内でしかスタイルが適用されないようになっています。
ビルド後はどのような形でCSSが適用されているかを、ディープセレクタ適用前と比較してみるとよくわかりますね。
【CSS】※一部抜粋
【Vue】
いかがでしょうか、Vue.jsの場合はたくさんのコンポーネントを使用するケースが多いかと思いますが、その分複雑になり、スタイルの適用や継承なども考慮しないと思わぬ修正コストが発生してしまいます。そんな時にはこのディープセレクタを使うことで、より効率的かつシンプルにスタイルを管理できるのではないでしょうか。 (参考にさせて頂いたサイト) スコープ付き CSS
<template> <div class="parent"> <p class="text">親コンポーネントの要素</p> <component-children /> </div> </template> <script> import ComponentChildren from '../components/ComponentChildren.vue' export default { name: 'ComponentParent', components: { ComponentChildren } } </script> <style scoped lang="scss"> p { color: red; } </style>【ComponentChildren.vue】
<template>
<div class="children">
<p class="text">子コンポーネントの要素</p>
</div>
</template>
<script>
export default {
name: 'ComponentChildren'
}
</script>
ビルドして確認してみますと、このように親コンポーネントの要素にはスタイルが適用されているのが確認できますが、子コンポーネントには同じセレクタで指定しているもののスタイルが適用されていません。
これはVueコンポーネントのstyle要素にscoped属性が適用されているのが理由です。つまり、通常ではコンポーネント内でしかスタイルが適用されないようになっています。
<style scoped> // コンポーネント内のみ適用されるスタイル </style>とりわけVue.jsでは、ビルド後にはコンポーネントごとに独自のdata属性が自動的に割り振られます。実際には下記のような形になります。 【HTML】※一部抜粋
<div class="parent" data-v-452d6c4c=""> <p class="text" data-v-452d6c4c="">親コンポーネントの要素</p> <div class="children" data-v-452d6c4c=""> <p class="text">子コンポーネントの要素</p> </div> </div>そこで、「ディープセレクタ」というものを使うことで、子コンポーネントの要素にもセレクタで指定できるようにしていきます。具体的には下記のように「>>>」もしくは「/deep/」という記述を追加します。 【Parent.vue】※一部抜粋
<style scoped lang="sass">
>>> .text {
color: red;
}
</style>
....もしくは
<style scoped lang="scss">
/deep/ .text {
color: red;
}
</style>
2通りありますが、SCSS記法の場合ですと「>>>」の記述が読み込まれないようですので、この場合は「/deep/」の方を選択するようにします。これで実際にブラウザで確認してみますと子コンポーネントにもスタイルが適用されているのが確認できます。
ビルド後はどのような形でCSSが適用されているかを、ディープセレクタ適用前と比較してみるとよくわかりますね。
【CSS】※一部抜粋
// ディープセレクタ適用前
.text[data-v-452d6c4c] {
color: red;
}
// ディープセレクタ適用後
[data-v-452d6c4c] .text {
color: red;
}
また特定の親要素の中にある、小コンポーネントの要素をディープセレクタで指定する場合には下記のようになります。
【Parent.vue】※一部抜粋
<style scoped lang="sass">
div:last-child >>> .text {
color: red;
}
</style>
....もしくは
<style scoped lang="scss">
div:last-child /deep/ .text {
color: red;
}
</style>
v-htmlのディレクティブで出力された要素にスタイルを適用する
先ほどは親コンポーネントから子コンポーネントへの適用でした。また、Vue.jsのディレクティブで、HTMLをそのまま出力できる「v-html」というものがあります。これは指定した要素の子要素に、対象のHTML文字列をそのまま出力できるものになります。 このv-htmlのディレクティブを使った時も実質的には親コンポーネントと子コンポーネントのような構成になるので、そのままですと下記のようにスタイルが適用されません。 【Vue】<template>
<div id="app">
<div v-html="content"></div>
</div>
</template>
<script>
export default {
data: function() {
return {
content: '<p class="text">v-htmlのディレクティブで出力された要素</p>'
}
}
}
</script>
<style scoped lang="scss">
.text {
color: red;
}
</style>
ブラウザで確認してもv-htmlで出力した要素にはスタイルが適用されていません。そこで先ほどと同じくディープセレクタを利用してスタイルを指定します。
【Vue】
<template>
<div id="app">
<div v-html="content"></div>
</div>
</template>
<script>
export default {
data: function() {
return {
content: '<p class="text">v-htmlのディレクティブで出力された要素</p>'
}
}
}
</script>
<style scoped lang="scss">
/deep/ .text {
color: red;
}
</style>
これで出力されたHTMLの要素にもスタイルを適用させることができました。
「/deep/」や「>>>」のセレクタ表記が効かない場合は「::v-deep」で対応
上記で説明しているディープセレクタですが、Sassなどモジュールのバージョンによっては機能しない、もしくはエラーとなる場合もあるようです。そんな時には代わりに「::v-deep」のセレクタを使うことで対応できます。使い方も上記のディープセレクタと同じ形になります。 【Parent.vue】※一部抜粋<style scoped lang="scss">
::v-deep .text {
color: red;
}
</style>
コンポーネント間はもちろんのこと、v-htmlなどで描画されたDOMにもスタイルを当てることができます。どうやら上記のセレクタは今後廃止されるようで、その対応策としてVue.jsの方で機能が追加されたようですね。今後はこちらをメインに使う方がいいかもしれませんね。
いかがでしょうか、Vue.jsの場合はたくさんのコンポーネントを使用するケースが多いかと思いますが、その分複雑になり、スタイルの適用や継承なども考慮しないと思わぬ修正コストが発生してしまいます。そんな時にはこのディープセレクタを使うことで、より効率的かつシンプルにスタイルを管理できるのではないでしょうか。 (参考にさせて頂いたサイト) スコープ付き CSS
categories
- WordPress(61)
- JavaScript(49)
- Vue.js(48)
- CSS(46)
- jQuery(34)
- Nuxt.js(22)
- Sass(21)
- Gulp(17)
- webpack(16)
- PHP(14)
- HTML(14)
- GSAP(11)
- React(10)
- Vite(9)
- Pug(9)
- Laravel(8)
- Cordova(8)
- Linux(7)
- Next.js(6)
- Apache(5)
- Shopify(4)
- REST API(4)
- Node.js(4)
- Smarty(3)
- Git(3)
- JSON(3)
- その他プログラミング(3)
- Google Apps API(3)
- Bootstrap(3)
- 環境構築・システム(3)
- TypeScript(2)
- EJS(2)
- RMS(2)
- Docker(2)
- Instagram API(2)
- Excel VBA(2)
- SVG(1)
- Dart(1)
- ECカートASP(1)
- Markdown(1)
- AMP(1)
- Nginx(1)
- XML(1)
- shellscript(1)
- Ruby(1)
- MySQL(1)