Edited at

ElementUI に Scoped CSS が適用されない問題対応策

More than 1 year has passed since last update.

宮崎在住エンジニアのジョウ(@JotarO_Oyanagi) です。

Vue.js 用 UI ライブラリ Element の要素に対し、Scoped CSS を使う場合に起きうる問題(後述)への対応策を紹介します。


TL;DR


  • Element の要素に Scoped CSS のスタイルが適用されないケースがある。

  • 原因は、通常の記述方法だとセレクタの子要素に data 属性がつき、そこに対してスタイルがあたるが、Element が書き出す一部の要素には data 属性がつかない。

  • 対応策としては /deep/ セレクタを使用する。


Scoped CSS とは

コンポーネントごとの CSS を書ける仕組みです。

<style scoped> とすると、そこに記述されたセレクタに対し、ユニークな data 属性がつき、その data 属性がセレクタに付加されます。

具体的にはどういうことか、公式の記述を抜粋してご紹介します。

参考:スコープ付き CSS

<style scoped>

.example {
color: red;
}
</style>

<template>
<div class="example">hi</div>
</template>

と記述すると、以下の状態で書き出されます。

<style>

.example[data-v-f3f3eg9] {
color: red;
}
</style>

<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>

data-v-f3f3eg9 という属性が付加されましたね。

セレクタに子要素を記述した場合には以下のようになります。

<style scoped>

.example .child {
color: red;
}
</style>

<template>
<div class="example">
<span class="child">hi</span>
</div>
</template>

この場合、以下の状態で書き出されます。

<style>

.example .child[data-v-f3f3eg9] {
color: red;
}
</style>

<template>
<div class="example">
<span class="child" data-v-f3f3eg9>hi</span>
</div>
</template>

親ではなく子の要素に data 属性がつきます。


Element が書き出す一部の要素には data 属性がつかない

以下の記述で書き出されたソースをご覧ください。

<style lang="sass" scoped>

.RootApp

.el-input
display: block
margin: 10px auto
width: 90%

&__inner
border-radius: 0
</style>

<template>
<div class="RootApp">
<el-input/>
</div>
</template>

この場合、以下の状態で書き出されます。

スクリーンショット 2017-12-26 19.11.31.png

<el-input> により .el-input.el-input__inner が書き出されています。

.el-input には data 属性がついているのでスタイルが適用されていますが、

スクリーンショット 2017-12-26 19.14.08.png

.el-input__inner には data 属性がないため、スタイルが適用されません。

これを解決するためにどうすればいいかと小一時間調べてみると、公式にその答えが書いてありました。

上で散々挙げたスコープ付き CSSの一番下に書いてあります。

Vue の公式はマジで優秀。


親要素に data 属性をつけるには、/deep/ セレクタを使う

vue-loader v12.2.0 以上 ならば、/deep/ セレクタという仕組みがあるとのことで、それを使うと data 属性が親要素につきます。

SCSS ならこう書くと

<style lang="sass" scoped>

- .RootApp
+ .RootApp /deep/

.el-input
display: block
margin: 10px auto
width: 90%

&__inner
border-radius: 0
</style>

こうなります。

スクリーンショット 2017-12-26 19.27.38.png

セレクタの親要素に data 属性がついて、無事 .el-input__inner にスタイルが適用されました!

SCSS ではなく、通常の CSS の書き方なら >>> を使います。

<style scoped>

.RootApp >>> .el-input__inner {
border-radius: 0
}
</style>


おわりに

Vue 関連は「公式読め」で解決することがホント多い。


参考資料