JavaScript
HTML5
CSS3
element
vue.js

スクロールバーで横幅がずれる

More than 1 year has passed since last update.


経緯

現在、以下のような環境でフロントエンドのサイトを作成しています。

名称
バージョン

Vue.js
2.3.4

Element UI
1.4.4

Element Theme Default
1.4.4

※ 他にもありますが、ここでは省略。ブラウザはiOSのChrome。


ハマり事象

私がハマった事象の概要は、「ElementUIのダイアログを開くと、fixedされているヘッダーが15pxくらい横に動く。(ダイアログを閉じた時も動く)」というものです。

これは、以下の条件の場合に発生します。


  1. ダイアログの裏のメインコンテンツが垂直方向のスクロールを表示している場合

  2. ElementUIのダイアログを、modal: trueかつlock-scroll: true(要はデフォルト)で開いた場合

  3. Flexboxなどでメインコンテンツを中央寄せしている場合

  4. メインコンテンツのヘッダーやナビゲーションをposition: fixedしていた場合

ソースコード例は以下のような感じとします。


index.html

<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>



app.js

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
}
})



app.scss

header {

height: 40px;
position: fixed;
width: 100%;
z-index: 10;
}

main {
// ヘッダーの分だけ余白を取る
padding-top: 40px;
}

body {
// スクロールの出る画面と出ない画面でずれるのを防止するため出しっ放しにする
overflow-y: scroll;
}


という感じです。良くあるヘッダー固定の構成です。


要因

ElementUIのダイアログを上記のオプション指定で開くと、ダイアログの裏のコンテンツのスクロールバーをoverflow: hiddenにしてくれます(bodyタグのスタイルに追加する)。

こうすることで、ダイアログ内をスクロールした時に、裏のコンテンツのスクロールが動くといった問題を解決できます。

また、同様にpadding-right: 15pxbodyタグにスタイル指定しています。

これは、スクロールバーの幅が15pxくらいなので、メインコンテンツのスクロールバーを消す分を打ち消しています。

しかし、このpadding-rightは、position: fixedであるヘッダーには機能せず、ヘッダーだけがスクロールバーが消える分を打ち消せずにずれてしまうわけです。


解決策

スクロールバーの幅に依存しないスタイル指定

上記を参照し、修正した結果のコードは以下のようになりました。

※ Sassのみの変更


app.scss

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); /* 追加 */
}


以上。