業務で複数の行および列が固定されたテーブルを作成するにあたり、FixedMidashi.jsを使用しました。大変使いやすいライブラリですが、IEで縦スクロールを行ったときに上部ヘッダが一瞬上下にがたつくため、その対処法を記載します。
発生条件
- ブラウザ ⇒ IE(私はIE11を使用しています。下のバージョンで現象が発生するかは未確認です)。
- 縦スクロールが一番上にある状態でマウスホイールでスクロール
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; /* 任意の数字*/
}
対応方法
FixedMidashiの公式ページに以下の記載があります。
FixedMidashiは固定する見出し部分を別 table にコピーし、それを元 table の上に重ねて表示する、 という方法で実現しています
FixedMidashi公式ページの概要より引用(http://hp.vector.co.jp/authors/VA056612/fixed_midashi/manual/index.html#summary)
対応方法としては元テーブルの上に重ねて表示された固定見出しに手を加えることになります。
行固定見出しへの対応
縦スクロール前
行固定見出しがvisibility: hidden
となっています。
縦スクロール後
visibility: visible
となります。
一番上からスクロールした時に行固定見出しの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');
}
}
})
行列固定見出しへの対応
このままだと横スクロールをした時に行固定見出しが左へ突き出てしまいます。
そのため、縦スクロールをしていない状態で横スクロールを行った際に行列固定見出しの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にまとめました。
<!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で縦スクロールした際にヘッダのがたつきが無くなります。