今日もvuejs-datepickerに絡めての話。

datepickerをインライン表示したら幅が固定になっていて困りました。

こうじゃなくて、

こっちにしたい。

コンポーネントのstyleを見ると幅300pxと固定になっています。これを幅100%にしたいの上書きします。

普通にグローバルなCSSに書いちゃう

このカレンダーの幅を指定しているのが、.vdp-datepicker__calendarクラスです。scopedスタイルでは書かれていないのでグローバルなスタイルとして書いてしまえば上書きできそうです。

なので、↓のようにしちゃえば万事解決です。

.vdp-datepicker__calendar {
  width: 100% !important;
}

一番シンプル。

だけど、複数箇所でカレンダーを使いたくて、それぞれ異なったスタイルにしたい場合はこれでは解決できません。

scopedとは別にstyleを書く

Vueコンポーネントのファイルに<style></style>を複数持ってしまうこともできます。片方はscoped、もう片方はグローバルという感じ。

<style scoped>
/* こっちはコンポーネント用のスタイル */
.style-for-this-component {
}
</style>

<style>
.vdp-datepicker__calendar {
  width: 100% !important;
}
</style>

これだとグローバルなCSSに書くのと変わりません。書くファイルが違うという程度。

部分的に適用したいという用途がある場合には問題となります。

scopedなstyleに書く

vuejs-datepickerのコンポーネントのルート要素は.vdp-datepickerです。

なので、自前のVueコンポーネント内でにdatepickerを置いた場合には、

<div data-v-356757fe="" data-v-73d4f3b9=""> <!-- 自前コンポーネント -->
   <div data-v-356757fe="" class="vdp-datepicker"> <!-- datepicker -->
     ...
     <div class="vdp-datepicker__calendar" style="position: static;"> <!-- styleをあてたい -->
     </div>
     ...
   </div>
</div>

といった構造になります。

もちろん↓のようにscopedなstyleを書くと、

<style scoped>
.vdp-datepicker__calendar {
  width: 100% !important;
}
</style>

生成されるのは次のようなcssなので、styleが適用されません。

.vdp-datepicker__calendar[data-v-356757fe] {
    width: 100% !important
}

そこでvue-loaderのディープセレクタという機能を使います。

scoped スタイルのセレクタを “deep” にしたい、つまり子コンポーネントに及ぼしたい場合は、>>> コンビネータを使用することができます:

ということで、コードは次のようになります。

<style scoped>
.vdp-datepicker >>> .vdp-datepicker__calendar {
  width: 100% !important
}
</style>

が、↓のようにコンパイルされます。

.vdp-datepicker[data-v-356757fe] .vdp-datepicker__calendar {
    width: 100% !important
}

Vueのデータ属性が親にしか付与されないため、子コンポーネントのスタイルをオーバーライドできるというわけです。