vue-js-modalをカスタマイズしたい!
vue-js-modalを使ってぼくのかんがえたさいきょうのモーダルを作ろうとしたところ、スタイルの適用でてこずったので記しておきます。
Qiita初投稿ですので、本題についてだけでなく記事自体の改善案についても、何かあればぜひコメントいただけると助かります。
環境
vue : 2.6.11
@vue/cli : 4.5.4
vue-js-modal : 2.0.0-rc.6
概要
今回やりたい実装
- vue-js-modalを使う(思い通りのスタイルを適用するためにvue-js-modal自体の導入を止めるという選択肢はない)
- モーダルが内包する要素についてだけでなく、モーダル自体のスタイルを変更する
- スタイルは単一ファイルコンポーネント内で完結させたい(色の変数を定義したscssファイルのインポートなどは除く)
前提
テンプレート側はこんな感じ
<modal name="foo" height="auto">
<h2 class="modal_title">省略</h2>
<div class="modal_body">省略</div>
</modal>
モーダルが内包しているh2やdivなどの要素については通常通りclassプロパティでクラスを指定してスタイルを適用することができます。
コンパイルして実際にモーダルを表示する時のhtmlの構造はこんな感じ
(data-vや中身など一部省略しています)
<div class="vm--container">
<div aria-expanded="true" class="vm--overlay">
<div class="vm--top-right-slot"></div>
</div>
<div aria-expanded="true" role="dialog" aria-modal="true" class="vm--modal" style="top: Npx; left: Npx; width: Npx; height: auto;">
<h2 class="modal_title">省略</h2>
<div class="modal_body">省略</div>
</div>
</div>
vm--overlay
が、モーダルを表示した時背景を暗くするための構造で、vm--modal
がモーダル本体です。
sytleプロパティはディスプレイのサイズに応じたデフォルト値が当てられ、今回の例ではheight
のみautoを指定したので上記のような感じになっています。
ドキュメントより
vue-js-modalのドキュメントには、クラスやスタイル関係のプロパティについて以下のような記載があります。
##classes: String | Array
List of class that will be applied to the modal window (not overlay, just the box).
→モーダルウィンドウ(オーバーレイではなくモーダルのボックス自体だけ)に適用されるクラスのリスト
##styles: String | Array | Object
Style that will be applied to the modal window.
→モーダルウィンドウに適用されるスタイル
素直な私「なるほど、この辺りのプロパティでクラス付与したりスタイル変更したりできるんだな!よし!」
〜そして意外と沼にハマってしまったのだった〜
*高さや幅、モーダルの表示位置などは別のプロパティがあります
詳しくはドキュメント参照
試したこと
以下は全て敗北の例で書くのも恥ずかしいくらいなので、サクサク読み飛ばしていただいて構いません。
classesでクラスを指定してそのクラスにスタイルを記述しよう!
modal_wrapperクラスに背景色などのスタイルを記述し、classesプロパティに渡してみた。
<modal name="foo" height="auto" classes="modal_wrapper">
<h2 class="modal_title">省略</h2>
<div class="modal_body">省略</div>
</modal>
【結果】
クラスは付与される(コンパイルされたhtml内でclass="vm--modal modal_wrapper"
のような形になる)が、スタイル自体は適用されず・・・(コンパイルするときに無視されている?)
恐らく、あくまでclassesプロパティはクラス名のみの付与で、.vueファイル内のscssがコンパイルされるときにstyleタグ内に記載したスタイルのクラス名とmodalのclassesプロパティで指定したクラス名が結びつかないとかそんな感じでしょうか。
stylesにスタイルを記述したクラス名を渡そう!
クラス名として指定してスタイルが反映されないならこうだ!
<modal name="foo" height="auto" styles="modal_wrapper">
<h2 class="modal_title">省略</h2>
<div class="modal_body">省略</div>
</modal>
【結果】
シンプルに特に何も起こらなかった。(それはそう)
勉強中の身のため解釈に自信はありませんが、おそらくスタイル関係のプロパティ全部を解釈して最終的にhtml側のstyleプロパティに渡しているから、この指定方法だとCSSの「modal_wrapper」という文字列として解釈されてしまう(そして普通に文法がおかしいので無視される)とかそんな感じかなぁと思いました。
stylesにはオブジェクトも渡せるみたいなので、なんか良きようにする方法はあるのかと思いましたが、有効な情報を探し出すことができませんでした。
その他
その他いろいろとこねくり回しましたが、結局どれも上記の例に起因する感じだったので割愛します。
解決方法
結論から申し上げますと、以下の例のようにstylesプロパティに適用したいスタイルを直接記述して渡すことによって解決しました。
<modal name="foo" height="auto" styles="
background: #e1e1e1;
border: 2px solid #05034f;
border-radius: 7px;">
<h2 class="modal_title">省略</h2>
<div class="modal_body">省略</div>
</modal>
確かにやりたいことは実装できているんですが、SCSSの変数が使えなかったり、styleタグの外にスタイルに関する記述があるという汚い感じになったりという問題があってあまりしっくりきません。
今後よりよい解決策が見つかった場合にはこの記事を更新させていただきます。
参考資料
- vue-js-modalドキュメント https://euvl.github.io/vue-js-modal/
- Vue.jsで簡単にモーダルが実装できる「vue-js-modal」『カバの樹』 https://www.kabanoki.net/3144/