22
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-09-17

経緯

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

名称 バージョン
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); /* 追加 */
}

以上。

22
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?