4
2

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 3 years have passed since last update.

ラクスAdvent Calendar 2020

Day 3

FixedMidashiで縦スクロールした時にIEの時だけヘッダが上下にがたつく挙動の対処法

Last updated at Posted at 2020-12-06

 業務で複数の行および列が固定されたテーブルを作成するにあたり、FixedMidashi.jsを使用しました。大変使いやすいライブラリですが、IEで縦スクロールを行ったときに上部ヘッダが一瞬上下にがたつくため、その対処法を記載します。

発生条件

  1. ブラウザ ⇒ IE(私はIE11を使用しています。下のバージョンで現象が発生するかは未確認です)。
  2. 縦スクロールが一番上にある状態でマウスホイールでスクロール

FixedMidashiを用いたテーブルの用意

まずFixedMidashi公式ページの使用方法に従ってテーブルを作成しました。
※業務ではdivモードを使用したので、divモードで記載します。

 ・tableタグをdivタグで囲み、そのdivタグにclassを付けます。
  (本記事ではclass="scroll_div"を付与)
 ・<table>_fixedhead="rows:x; cols:y"を付けます。
  (x,yにはそれぞれ固定したい行数、列数を記載)


<body>
    <div class="scroll_div">
        <table _fixedhead="rows:2; cols:2">
            
      ~省略~

        </table>
    </div>
</body>

onloadイベントでFixedMidashi.create()を呼び出します。

window.onload = function () {
            FixedMidashi.create();
}

・bodyタグを囲っている<div class="scroll_div">overflow: autoを付けます。

table tr,
table th,
table td {
    border: 1px solid black;
}
table {
    border-collapse: collapse;
    white-space: nowrap;
    box-sizing: content-box;
}
.scroll_div {
    overflow: auto;
    width: 312px; /* 任意の数字*/
    height: 159px; /* 任意の数字*/
}

table.PNG

対応方法

FixedMidashiの公式ページに以下の記載があります。

FixedMidashiは固定する見出し部分を別 table にコピーし、それを元 table の上に重ねて表示する、 という方法で実現しています

  FixedMidashi公式ページの概要より引用(http://hp.vector.co.jp/authors/VA056612/fixed_midashi/manual/index.html#summary)

 対応方法としては元テーブルの上に重ねて表示された固定見出しに手を加えることになります。

行固定見出しへの対応

縦スクロール前
 行固定見出しがvisibility: hiddenとなっています。
scroll.PNG

縦スクロール後
 visibility: visibleとなります。
scrolled.PNG

一番上からスクロールした時に行固定見出しのvisibilityの値がhiddenからvisibleへ変わり、またスクロールを一番上へ戻すとvisibleからhiddenへ変わります。
これががたつきの要因となっています。
ここで、visibilityが常にvisibleとなるクラスを作成します。

// スクロールがたつき対応
.copyheader_visible {
   visibility: visible !important;
}

スクロールバーが一番上に来た時に行固定見出しにclass="copyheader_visible"を追加します。

 // IEの時のみ対応
 if (navigator.userAgent.match(/MSIE 10/i) || navigator.userAgent.match(/Trident\/7\./)) {
     // 行固定見出しに、スクロールがたつき対応クラスを追加
     $(".scroll_div").eq(2).addClass("copyheader_visible");

     $(".scroll_div").scroll(function () {
        // 縦スクロール量を取得
        var scrollTop = $('.scroll_div').scrollTop();

       if (scrollTop == 0) {
          // 縦スクロールの位置が一番上に来た時
          var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
          if (!topHeaderVisible) {
            // 行固定見出しをvisibleとする
            $('.scroll_div').eq(2).addClass('copyheader_visible');
          }
       } else {
          var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
          if (topHeaderVisible) {
             $('.scroll_div').eq(2).removeClass('copyheader_visible');
          }
       }
  })
            

行列固定見出しへの対応

このままだと横スクロールをした時に行固定見出しが左へ突き出てしまいます。
scrollLeft.PNG

そのため、縦スクロールをしていない状態で横スクロールを行った際に行列固定見出しvisibilityが常にvisibleとなるようにします。

  /* ~該当箇所のみ抜粋~ */

 // 縦スクロール量を取得
 var scrollTop = $('.scroll_div').scrollTop();
// 横スクロール量を取得
 var scrollLeft = $('.scroll_div').scrollLeft();

 if (scrollTop == 0 && scrollLeft == 0) {
    // 縦スクロールの位置が一番上かつ、横スクロールの位置が一番左の時
    var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
    if (!topHeaderVisible) {
        // 行固定見出しをvisibleとする
        $('.scroll_div').eq(2).addClass('copyheader_visible');
    }
 }else if(scrollTop == 0 && scrollLeft != 0){
       // 縦スクロールの位置が一番上のときかつ、横スクロールされている時
       var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
       var leftTopHeaderVisible = $('.scroll_div').eq(3).hasClass("copyheader_visible");
       if (!topHeaderVisible) {
          // 行固定見出しをvisibleとする
          $('.scroll_div').eq(2).addClass('copyheader_visible');
       }
       if (!leftTopHeaderVisible) {
          // 行列固定見出しをvisibleとする
          $('.scroll_div').eq(3).addClass('copyheader_visible');
       }
 } else {
        var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
        var leftTopHeaderVisible = $('.scroll_div').eq(3).hasClass("copyheader_visible");
          // 初期状態に戻す
          if (topHeaderVisible) {
               $('.scroll_div').eq(2).removeClass('copyheader_visible');
          }
          if(leftTopHeaderVisible){
               $('.scroll_div').eq(3).removeClass('copyheader_visible');
          }

}

まとめると

以上をまとめると以下のようなコードになります。
※一枚のhtmlにまとめました。

table.html
<!DOCTYPE html>
<html>
<head>
    <title>FixedMidashi</title>
    <meta charset="utf-8" />
    <style type="text/css">
        .scroll_div {
            overflow: auto;
            width: 312px;
            height: 159px;
        }
        table tr,
        table th,
        table td {
            border: 1px solid black;
        }
        table {
            border-collapse: collapse;
            white-space: nowrap;
            box-sizing: content-box;
        }
        /* がたつき対応 */
        .copyheader_visible {
            visibility: visible !important;
        }
    </style>
    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script src="./fixed_midashi_1.11/fixed_midashi.js"></script>
    <script>
        window.onload = function () {
            FixedMidashi.create();
            // IEの時のみ対応
            if (navigator.userAgent.match(/MSIE 10/i) || navigator.userAgent.match(/Trident\/7\./)) {
                // 行固定見出しに、スクロールがたつき対応クラスを追加
                $(".scroll_div").eq(2).addClass("copyheader_visible");

                $(".scroll_div").scroll(function () {
                    // 縦スクロール量を取得
                    var scrollTop = $('.scroll_div').scrollTop();
                    // 横スクロール量を取得
                    var scrollLeft = $('.scroll_div').scrollLeft();

                    if (scrollTop == 0 && scrollLeft == 0) {
                        // 縦スクロールの位置が一番上かつ、横スクロールの位置が一番左の時
                        var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
                        if (!topHeaderVisible) {
                            // 行固定見出しをvisibleとする
                            $('.scroll_div').eq(2).addClass('copyheader_visible');
                        }
                    }else if(scrollTop == 0 && scrollLeft != 0){
                        // 縦スクロールの位置が一番上のときかつ、横スクロールされている時
                        var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
                        var leftTopHeaderVisible = $('.scroll_div').eq(3).hasClass("copyheader_visible");
                        if (!topHeaderVisible) {
                            // 行固定見出しをvisibleとする
                            $('.scroll_div').eq(2).addClass('copyheader_visible');
                        }
                        if (!leftTopHeaderVisible) {
                            // 行列固定見出しをvisibleとする
                            $('.scroll_div').eq(3).addClass('copyheader_visible');
                        }
                    } else {
                        var topHeaderVisible = $('.scroll_div').eq(2).hasClass("copyheader_visible");
                        var leftTopHeaderVisible = $('.scroll_div').eq(3).hasClass("copyheader_visible");
                        // 初期状態に戻す
                        if (topHeaderVisible) {
                            $('.scroll_div').eq(2).removeClass('copyheader_visible');
                        }
                        if(leftTopHeaderVisible){
                            $('.scroll_div').eq(3).removeClass('copyheader_visible');
                        }

                    }
                })
            }
        };

    </script>
</head>
<body>
    <div class="scroll_div">
        <table _fixedhead="rows:2; cols:2">
            ~省略~
        </table>
    </div>
</body>
</html>

これでIEで縦スクロールした際にヘッダのがたつきが無くなります。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?