【更新日 : 】
【JavaScript】スマホで画面に収まらないtableを横スクロールさせる
- Category:
- JavaScript
- Tags:
- JavaScript, Vanilla JS, スクロール, 表組み
スマホで画面に収まらないtableを横スクロールに切り替えるJavaScriptサンプルです。
簡易的なものならCSSのみでも可能ですが、CMSでtableタグのみ動的に挿入される場合や、
tableごとに本来の幅でスクロールさせたい場合などに有効だと思います。
See the Pen Table formatting: horizontal scrolling on mobile Vanilla JS by web_nak (@web_walking_nak) on CodePen.
HTML・CSS
table要素が画面外へはみ出ても問題ないよう
エリア全体を覆う要素に overflow:hidden; を設定してください。
JavaScript
tableタグにclass is-no-scroll
が付与されている場合は本処理の対象外になります。
//表組み スクロール切り替え
const tables = document.querySelectorAll('table');
if(tables.length > 0) {
//スクロール処理を発火させるブレイクポイント
const breakPoint = 767;
//tableごとの処理
tables.forEach((table) => {
//tableに除外class "is-no-scroll" が付与されている場合は処理しない
if(!table.classList.contains('is-no-scroll')) {
//スクロール用div要素作成
const inner = document.createElement('div');
inner.classList.add('table-inner');
const wrap = document.createElement('div');
wrap.classList.add('table-wrap');
//スクロール用div要素挿入
table.parentNode.insertBefore(inner, table);
inner.appendChild(table);
inner.parentNode.insertBefore(wrap, inner);
wrap.appendChild(inner);
//スクロール発火フラグ
let scrollFlg = false;
//table widthの設定値を取得
table.baseWidth = table.style.width;
//スクロール関数
const tableScroll = () => {
//スクロールが発火していたら設定をリセット
if(scrollFlg) {
inner.removeAttribute('style');
wrap.removeAttribute('style');
table.style.width = table.baseWidth;
scrollFlg = false;
}
//ブレイクポイント以下の場合のみ処理
const winWidth = window.innerWidth;
if(winWidth > breakPoint) {
return;
}
//tableのベース幅を取得
let tableWidth = table.offsetWidth;
const wrapWidth = wrap.offsetWidth;
//tableの幅がwrapの幅以上の場合は本来の幅をチェック
if(wrapWidth <= tableWidth) {
//tableに100%以外のwidth指定が入っている場合
if(table.baseWidth !== '' && table.baseWidth !== '100%') {
tableWidth = parseFloat(table.baseWidth) + 1;
} else {
table.baseWidth = table.style.width;
table.style.width = 'auto';
inner.style.width = '9999px';
tableWidth = table.offsetWidth;
inner.style.width = '';
table.style.width = table.baseWidth;
console.log(tableWidth,table.baseWidth);
}
}
//tableがwrapの幅を超えている場合スクロール発火
if(wrapWidth < tableWidth) {
//wrapリセット
wrap.removeAttribute('style');
wrap.style.overflowX = 'hidden';
//wrapの左右の余白を取得
const wrapLeftMargin = wrap.getBoundingClientRect().left;
const wrapRightMargin = winWidth - parseFloat(wrap.getBoundingClientRect().right);
//wrapを画面幅いっぱいに広げる
wrap.style.overflowX = 'scroll';
wrap.style.marginLeft = '-' + wrapLeftMargin + 'px';
wrap.style.marginRight = '-' + wrapRightMargin + 'px';
//innerにtable本来の幅 + 左右余白を設定
inner.style.boxSizing = 'content-box';
inner.style.paddingLeft = wrapLeftMargin + 'px';
inner.style.paddingRight = wrapRightMargin + 'px';
inner.style.width = (tableWidth + 1) + 'px'; //少数点分の繰り上げ
//スクロール発火フラグセット
scrollFlg = true;
}
}
//スクロール関数呼び出し
tableScroll();
//リサイズイベント
let lastInnerWidth = window.innerWidth;
window.addEventListener('resize', function() {
//画面の横サイズが変わった時のみ発火
if (lastInnerWidth !== window.innerWidth) {
//スクロール関数呼び出し
tableScroll();
//横幅を保存
lastInnerWidth = window.innerWidth;
}
});
}
});
}