プログラミング備忘録 foo

横スクロール式

目的

  • 横スクロール式にして、横幅を気にせずtableを作りたい。
  • 横スクロール可能である事を示すために右矢印を付けて、横スクロールしたら消えるようにして、横スクロール停止状態が指定時間経過すると再表示されるようにしたい。
  • 画面内に収まる横幅の時は右矢印を最初から非表示にしたい。

実行結果

観光地名 所在地 主な分類 見どころ ベストシーズン 備考
富士山 静岡・山梨 山岳・自然 登頂・5合目 07月〜09月 標高3776mを誇る日本最高峰の山であり、その美しい山容は日本の象徴として世界的に知られ、ユネスコの世界文化遺産にも登録されています。
金閣寺 京都府 寺院・歴史 黄金の舎利殿 通年(冬の雪) 正式名称を鹿苑寺といい、舎利殿の外壁に純金が貼られた煌びやかな姿が特徴的で、室町時代の北山文化を象徴する歴史的価値の高い寺院です。
厳島神社 広島県 神社・歴史 海上の大鳥居 秋(紅葉) 瀬戸内海の潮の満ち引きによって海に浮かんでいるように見える大鳥居や社殿が特徴で、日本三景の一つに数えられる極めて稀な建築様式です。
白川郷 岐阜県 集落・文化 合掌造り集落 冬(ライトアップ) 豪雪地帯特有の急勾配な屋根を持つ合掌造り民家が今なお現存しており、日本の原風景とも言える美しい景観は世界文化遺産として高く評価されています。
華厳の滝 栃木県 滝・自然 97mの落差 秋(紅葉) 中禅寺湖の水が高さ97メートルの岸壁を一気に落下する様子は壮観であり、日本三名瀑の1つとして四季折々の自然の美しさを楽しめる名所です。

解説

  • 長文でも改行されず、文字が横へ伸びていきます。ハミ出す場合は自動で横スクロール可能な仕様になり、初期画面では右矢印が出ます。
  • 横スクロールで右矢印は消え、スクロール停止状態が2秒続くと右矢印が再表示されます。
  • 画面内に収まる横幅の時は右矢印が最初から非表示になります。画面内に収まりきらない横幅の時は自動で横スクロール式になるので使い勝手が良いです。

HTML

<div class="layout_6_2">
	<table>
		<thead>
			<tr>
				<th>観光地名</th>
				<th>所在地</th>
				<th>主な分類</th>
				<th>見どころ</th>
				<th>ベストシーズン</th>
				<th>備考</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>富士山</td>
				<td>静岡・山梨</td>
				<td>山岳・自然</td>
				<td>登頂・5合目</td>
				<td>07月〜09月</td>
				<td>標高3776mを誇る日本最高峰の山であり、その美しい山容は日本の象徴として世界的に知られ、ユネスコの世界文化遺産にも登録されています。</td>
			</tr>
			<tr>
				<td>金閣寺</td>
				<td>京都府</td>
				<td>寺院・歴史</td>
				<td>黄金の舎利殿</td>
				<td>通年(冬の雪)</td>
				<td>正式名称を鹿苑寺といい、舎利殿の外壁に純金が貼られた煌びやかな姿が特徴的で、室町時代の北山文化を象徴する歴史的価値の高い寺院です。</td>
			</tr>
			<tr>
				<td>厳島神社</td>
				<td>広島県</td>
				<td>神社・歴史</td>
				<td>海上の大鳥居</td>
				<td>秋(紅葉)</td>
				<td>瀬戸内海の潮の満ち引きによって海に浮かんでいるように見える大鳥居や社殿が特徴で、日本三景の一つに数えられる極めて稀な建築様式です。</td>
			</tr>
			<tr>
				<td>白川郷</td>
				<td>岐阜県</td>
				<td>集落・文化</td>
				<td>合掌造り集落</td>
				<td>冬(ライトアップ)</td>
				<td>豪雪地帯特有の急勾配な屋根を持つ合掌造り民家が今なお現存しており、日本の原風景とも言える美しい景観は世界文化遺産として高く評価されています。</td>
			</tr>
			<tr>
				<td>華厳の滝</td>
				<td>栃木県</td>
				<td>滝・自然</td>
				<td>97mの落差</td>
				<td>秋(紅葉)</td>
				<td>中禅寺湖の水が高さ97メートルの岸壁を一気に落下する様子は壮観であり、日本三名瀑の1つとして四季折々の自然の美しさを楽しめる名所です。</td>
			</tr>
		</tbody>
	</table>
	<div class="layout_6_2_b"></div>
</div>
  • 画面内に収まる横幅の時に右矢印が最初から非表示になるか確かめる時は、行数を削除してください。

CSS

.layout_6_2 {
	width: 0;
	min-width: 96%;
	margin-top: 0px;
	margin-right: auto;
	margin-bottom: 40px;
	margin-left: auto;
	position: relative;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

.layout_6_2 table {
	width: 100%;
	border: solid 2px #000000;
	border-collapse: collapse;
}

.layout_6_2 table th {
	background-color: #E9E9E9;
	text-align: center;
}

.layout_6_2 table th:last-child {
	text-align: left;
	padding-top: 0px;
	padding-right: 0px;
	padding-bottom: 0px;
	padding-left: 10px;
}

.layout_6_2 table th,.layout_6_2 table td {
	font-size: 14px;
	width: 0;
	padding-top: 5px;
	padding-right: 5px;
	padding-bottom: 5px;
	padding-left: 5px;
	border: dotted 1px #333333;
	white-space: nowrap;
}

.layout_6_2 table td:nth-child(1) {
	text-align: center;
	padding-top: 10px;
	padding-right: 10px;
	padding-bottom: 10px;
	padding-left: 10px;
}

.layout_6_2 table td:nth-child(n+2) {
	text-align: left;
	padding-top: 10px;
	padding-right: 10px;
	padding-bottom: 10px;
	padding-left: 10px;
}

.layout_6_2_b {
	width: 48px;
	height: 48px;
	background-color: #064458;
	display: flex;
	align-items: center;
	justify-content: center;
	pointer-events: none;
	border-radius: 50%;
	position: absolute;
	top: 50%;
	right: 10px;
	transform: translateY(-50%);
	transition: opacity 0.3s;
	opacity: 0;
	pointer-events: none;
}

.layout_6_2_b::after {
	content: "";
	width: 12px;
	height: 12px;
	margin-top: 0px;
	margin-right: 0px;
	margin-bottom: 0px;
	margin-left: -6px;
	border-top: solid 4px #FFFFFF;
	border-right: solid 4px #FFFFFF;
	transform: rotate(45deg);
}

.layout_6_2_b.visible {
	opacity: 0.7;
	pointer-events: auto;
}
  • 33行目のwidth: 0;は左右に不要な余白を作らないために書いています。

JavaScript

document.addEventListener('DOMContentLoaded', function() {
	const tableWrap = document.querySelector('.layout_6_2');
	const arrow = document.querySelector('.layout_6_2_b');

	if (!tableWrap || !arrow) return;

	function checkScrollRequirement() {
		const isScrollable = tableWrap.scrollWidth > tableWrap.clientWidth + 1;
		
		if (isScrollable && tableWrap.scrollLeft < 5) {
			arrow.classList.add('visible');
		} else {
			arrow.classList.remove('visible');
		}
	}

	checkScrollRequirement();
	window.addEventListener('resize', checkScrollRequirement);

	let scrollTimeout;

	tableWrap.addEventListener('scroll', function() {
		arrow.classList.remove('visible');
		
		clearTimeout(scrollTimeout);
		scrollTimeout = setTimeout(() => {
			const canScrollMore = tableWrap.scrollWidth > (tableWrap.scrollLeft + tableWrap.clientWidth + 5);
			if (canScrollMore) {
				arrow.classList.add('visible');
			}
		}, 2000);
	}, { passive: true });
});
  • 横スクロールで右矢印が消えますが、横スクロール停止状態が2秒続くと再表示されます。31行目で2000と指定しているので2秒となります。2秒=2000ミリ秒なので3秒なら3000、4.5秒なら4500となります。