子コンポーネントや、v-htmlで生成された要素にもスタイルを適用する方法[Vue.js]

子コンポーネントや、v-htmlで生成された要素にもスタイルを適用する方法[Vue.js]
この記事をシェアする:
Vue.jsを使用している案件では、ほとんどの場合
単一コンポーネントを使用していて、css の部分は、ほぼ次のように書かれていると思います。

[Vue.jsの単一コンポーネントを使った案件で想定される一般的な style の状態]

<style scoped>
.myclass {
  font-size: 3rem;
}
</style>

↑そうです。1行目にあるように、 scoped です。
この scoped 属性がstyleタグについている場合、Vue.jsの単一コンポーネントでは、
「そのコンポーネントにのみ」スタイルを適用することができます。

ただ、案件の中には
「案件全体のルールとしては、cssはscopedで運用」されているものの
ある一定の導線においてのみ
「子コンポーネントにもスタイルを適用したい」、
そういったケースが出てくる場合があります。

そんな時に使える方法について、今回は書いていきたいと思います。

結論から。「:deep」を使用すると、scopedされたstyle指定の中からも、子コンポーネントにも適用されるスタイルを記述できる

Vue.jsの単一コンポーネント内で、styleタグにscoped属性がついている場合、「そのコンポーネントにのみ」スタイルが適用されます。

そのルール下で、「子コンポーネント」にもスタイルを適用したい場合、次のように書きます。

[子コンポーネントにもstyleを効かせたい場合]

<style scoped>
:deep(.myclass) {
  font-size: 3rem;
}
</style>

↑このようにすると、scoped状態では通常は効かないスタイルを、
子コンポーネントにも効かせることが可能になります。

v-htmlで生成されたコンテンツにスタイル適用する場合にも使える


v-htmlを通して生成されたコンテンツが持っている、dataの値の中にある class には、
スタイルを適用しようとしても、普通に書いただけではスタイルが効きません。

これに対しても、:deep を使うことで、スタイルを適用することが可能です。
どう言うことかと言うと、次のようなことです。

例えば、表示したいdataの中身がhtmlタグを含むもので、
それを v-html を使って、ユーザーにはhtmlとして見てもらいたい場合。

次のようなdataがあったとして、

posts: [
  { 
    id: 1,
    mytitle: 'Vue.jsをつかってみる',
    mycontent: '双方向の<span class="myclass">データバインディング</span>'
  },
  { 
    id: 2,
    mytitle: 'WordPressをつかってみる',
    mycontent: 'この<span class="myclass">WordPress</span>というのは、'
  },
...(中略)...

template側は、例えば次のように書くと思います。
5行目の v-html で、htmlタグを含む data を html として展開しています。

<div v-for="item in mydata.posts" :key="item.id">
  <h2>
    {{item.mytitle}}
  </h2>
  <p v-html="item.mycontent"></p>
</div>

ただしこのように v-html で展開した data の中にある class にスタイルを当てたい場合、
通常の記法ではスタイルを当てることができません。
この例で言うと、
5行目のv-htmlで展開している item.mycontent が持っている、 myclass に対してスタイルを当てたい場合を想定しています。

で、どうするかと言うと、次のように書き換えるわけですね。上のセクションの例とまったく同じく、:deep を使用します。

<style scoped>
:deep(.myclass) {
  font-size: 3rem;
}
</style>

↑このように :deep を使用してあげると
v-htmlをつかって生成されたコンテンツにも、しっかりスタイルを適用することが可能になります。

Vue.js公式サイトでの解説

:deep に関するVue.js公式サイト内の解説は、次のページにあります。
SFC CSS Features | Vue.js
↑こちらのページでは、他にも

・scopedの代替手段としてのmodule化の方法
・cssやtemplateを別ファイルとして管理する方法

などが掲載されており、場合によっては役立つかもしれません。

この記事のまとめ

今回は、とても手短ながら、

「案件全体のルールとしては、cssはscopedで運用」されているものの
ある一定の導線においてのみ
「子コンポーネントにもスタイルを適用したい」、

そんな場合に使える

Vue.js の 「:deep」(:deep疑似クラスと呼ばれます) について書いてみました。

この「:deep」 、
私自身、実際の案件で使う機会が時々あったりした方法なので、覚えておくと何かの役に立つかもしれません。

※この記事は、内容の品質向上を目的に、随時更新を行う場合があります。

この記事をシェアする: