経緯
現在、以下のような環境でフロントエンドのサイトを作成しています。
名称 | バージョン |
---|---|
Vue.js | 2.3.4 |
Element UI | 1.4.4 |
Element Theme Default | 1.4.4 |
※ 他にもありますが、ここでは省略。ブラウザはiOSのChrome。
ハマり事象
私がハマった事象の概要は、「ElementUIのダイアログを開くと、fixedされているヘッダーが15pxくらい横に動く。(ダイアログを閉じた時も動く)」というものです。
これは、以下の条件の場合に発生します。
- ダイアログの裏のメインコンテンツが垂直方向のスクロールを表示している場合
- ElementUIのダイアログを、
modal: true
かつlock-scroll: true
(要はデフォルト)で開いた場合 - Flexboxなどでメインコンテンツを中央寄せしている場合
- メインコンテンツのヘッダーやナビゲーションを
position: fixed
していた場合
ソースコード例は以下のような感じとします。
<html>
<head>
<!--省略-->
</head>
<body>
<div id="app">
<header>
<p>ヘッダー</p>
</header>
<main>
<p>メインコンテンツ</p>
<el-button type="primary" @click="enabledDialog = true">
ボタン
</el-button>
<el-dialog title="ダイアログ" :visible.sync="enabledDialog">
ダイアログの中身
</el-dialog>
</main>
</div>
</body>
</html>
window.Vue = require('vue');
import ElementUI from 'element-ui'
import locale from 'element-ui/lib/locale/lang/ja'
import 'element-theme-default/theme/index.css'
Vue.use(ElementUI, {locale})
const vm = new Vue({
el: '#app',
data: {
enabledDialog: false
}
})
header {
height: 40px;
position: fixed;
width: 100%;
z-index: 10;
}
main {
// ヘッダーの分だけ余白を取る
padding-top: 40px;
}
body {
// スクロールの出る画面と出ない画面でずれるのを防止するため出しっ放しにする
overflow-y: scroll;
}
という感じです。良くあるヘッダー固定の構成です。
要因
ElementUIのダイアログを上記のオプション指定で開くと、ダイアログの裏のコンテンツのスクロールバーをoverflow: hidden
にしてくれます(body
タグのスタイルに追加する)。
こうすることで、ダイアログ内をスクロールした時に、裏のコンテンツのスクロールが動くといった問題を解決できます。
また、同様にpadding-right: 15px
もbody
タグにスタイル指定しています。
これは、スクロールバーの幅が15pxくらいなので、メインコンテンツのスクロールバーを消す分を打ち消しています。
しかし、このpadding-right
は、position: fixed
であるヘッダーには機能せず、ヘッダーだけがスクロールバーが消える分を打ち消せずにずれてしまうわけです。
解決策
上記を参照し、修正した結果のコードは以下のようになりました。
※ Sassのみの変更
header {
height: 40px;
position: fixed;
// width: 100%;
width: calc(100vw - 15px); /* 追加 */
z-index: 10;
}
main {
// ヘッダーの分だけ余白を取る
padding-top: 40px;
}
body {
// スクロールの出る画面と出ない画面でずれるのを防止するため出しっ放しにする
overflow-y: scroll;
width: calc(100vw - 15px); /* 追加 */
}
以上。