WordPressなどで動的にメニューやコンテンツを増やせる状態にあった場合、要素の横幅や数が増えすぎることによってカラム落ちを起こすことがあります。
CSSでの定義はあらかじめ横幅を指定しておく必要があるため、動的な横幅のサイズ変動には対応できずにカラム落ちする場合があります。このような問題は特にメニューなどで発生することが多いでしょう。今回はJavascriptでカラム落ちを感知して、処理を実行する方法を紹介します。
これによってメニューのカラム落ちの場合には展開式メニューに変更したりすることも可能になります。
コードの紹介
<meta name="viewport" content="width=device-width, initial-scale=1.0">
justify-content: space-between;
/* リスト(ul, ol)のレイアウト設定 */
justify-content: space-between;
<!-- カラム落ちの検出対象となるメニューエリア -->
<header class="column_check">
<li><a href="">トップページ</a></li>
<li><a href="">個人のお客様</a></li>
<li><a href="">法人のお客様</a></li>
<li><a href="">サービスの紹介</a></li>
<li><a href="">会社概要</a></li>
<li><a href="">お知らせ</a></li>
<li><a href="">よくある質問</a></li>
<li><a href="">お問い合わせ・手続き</a></li>
function checkColumnDrop() {
const columnCheck = document.querySelector('.column_check');
const children = Array.from(columnCheck.children);
const referenceElement = children[0];
const referenceBottom = referenceElement.offsetTop + referenceElement.offsetHeight;
let columnDropped = false;
for (let i = 1; i < children.length; i++) {
const child = children[i];
if (child.offsetTop > referenceBottom && !child.dataset.dropped) {
child.dataset.dropped = "true";
children.forEach(child => delete child.dataset.dropped);
document.addEventListener('DOMContentLoaded', checkColumnDrop);
window.addEventListener('resize', checkColumnDrop);
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* 全体のヘッダーのパディング設定 */
header {
padding: 0 15px;
}
/* タイトルのフォントサイズ設定 */
h1 {
font-size: 20px;
}
/* メニューエリアのレイアウト設定 */
.column_check {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
}
/* リスト(ul, ol)のレイアウト設定 */
ul, ol {
display: flex;
justify-content: space-between;
}
/* リストアイテムの左側マージン設定 */
ul li, ol li {
margin-left: 20px;
list-style: none;
}
/* リンクのデザイン設定 */
ul li a, ol li a {
color: #323232;
text-decoration: none;
}
</style>
</head>
<body>
<!-- カラム落ちの検出対象となるメニューエリア -->
<header class="column_check">
<h1>SAMPLE</h1>
<ul>
<li><a href="">トップページ</a></li>
<li><a href="">個人のお客様</a></li>
<li><a href="">法人のお客様</a></li>
<li><a href="">サービスの紹介</a></li>
</ul>
<ol>
<li><a href="">会社概要</a></li>
<li><a href="">お知らせ</a></li>
<li><a href="">よくある質問</a></li>
<li><a href="">お問い合わせ・手続き</a></li>
</ol>
</header>
<script>
function checkColumnDrop() {
const columnCheck = document.querySelector('.column_check');
const children = Array.from(columnCheck.children);
const referenceElement = children[0];
const referenceBottom = referenceElement.offsetTop + referenceElement.offsetHeight;
let columnDropped = false;
for (let i = 1; i < children.length; i++) {
const child = children[i];
if (child.offsetTop > referenceBottom && !child.dataset.dropped) {
child.dataset.dropped = "true";
columnDropped = true;
}
}
if (columnDropped) {
alert('カラム落ちしました!');
//ここに処理を書く
}
if (!columnDropped) {
children.forEach(child => delete child.dataset.dropped);
}
}
document.addEventListener('DOMContentLoaded', checkColumnDrop);
window.addEventListener('resize', checkColumnDrop);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* 全体のヘッダーのパディング設定 */
header {
padding: 0 15px;
}
/* タイトルのフォントサイズ設定 */
h1 {
font-size: 20px;
}
/* メニューエリアのレイアウト設定 */
.column_check {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
}
/* リスト(ul, ol)のレイアウト設定 */
ul, ol {
display: flex;
justify-content: space-between;
}
/* リストアイテムの左側マージン設定 */
ul li, ol li {
margin-left: 20px;
list-style: none;
}
/* リンクのデザイン設定 */
ul li a, ol li a {
color: #323232;
text-decoration: none;
}
</style>
</head>
<body>
<!-- カラム落ちの検出対象となるメニューエリア -->
<header class="column_check">
<h1>SAMPLE</h1>
<ul>
<li><a href="">トップページ</a></li>
<li><a href="">個人のお客様</a></li>
<li><a href="">法人のお客様</a></li>
<li><a href="">サービスの紹介</a></li>
</ul>
<ol>
<li><a href="">会社概要</a></li>
<li><a href="">お知らせ</a></li>
<li><a href="">よくある質問</a></li>
<li><a href="">お問い合わせ・手続き</a></li>
</ol>
</header>
<script>
function checkColumnDrop() {
const columnCheck = document.querySelector('.column_check');
const children = Array.from(columnCheck.children);
const referenceElement = children[0];
const referenceBottom = referenceElement.offsetTop + referenceElement.offsetHeight;
let columnDropped = false;
for (let i = 1; i < children.length; i++) {
const child = children[i];
if (child.offsetTop > referenceBottom && !child.dataset.dropped) {
child.dataset.dropped = "true";
columnDropped = true;
}
}
if (columnDropped) {
alert('カラム落ちしました!');
//ここに処理を書く
}
if (!columnDropped) {
children.forEach(child => delete child.dataset.dropped);
}
}
document.addEventListener('DOMContentLoaded', checkColumnDrop);
window.addEventListener('resize', checkColumnDrop);
</script>
</body>
</html>
コードを解説
CSSの説明は割愛します。
HTMLの解説
今回は『header』のメニュー内をカラム検知します。
カラム落ちを検知するボックスにハンドリング用にクラス名『column_check』を付与しておきます。
この直下の横並びが崩れた場合に処理が実行されます。
<!-- カラム落ちの検出対象となるメニューエリア -->
<header class="column_check">
<li><a href="">トップページ</a></li>
<li><a href="">個人のお客様</a></li>
<li><a href="">法人のお客様</a></li>
<li><a href="">サービスの紹介</a></li>
<li><a href="">会社概要</a></li>
<li><a href="">お知らせ</a></li>
<li><a href="">よくある質問</a></li>
<li><a href="">お問い合わせ・手続き</a></li>
<!-- カラム落ちの検出対象となるメニューエリア -->
<header class="column_check">
<h1>SAMPLE</h1>
<ul>
<li><a href="">トップページ</a></li>
<li><a href="">個人のお客様</a></li>
<li><a href="">法人のお客様</a></li>
<li><a href="">サービスの紹介</a></li>
</ul>
<ol>
<li><a href="">会社概要</a></li>
<li><a href="">お知らせ</a></li>
<li><a href="">よくある質問</a></li>
<li><a href="">お問い合わせ・手続き</a></li>
</ol>
</header>
<!-- カラム落ちの検出対象となるメニューエリア -->
<header class="column_check">
<h1>SAMPLE</h1>
<ul>
<li><a href="">トップページ</a></li>
<li><a href="">個人のお客様</a></li>
<li><a href="">法人のお客様</a></li>
<li><a href="">サービスの紹介</a></li>
</ul>
<ol>
<li><a href="">会社概要</a></li>
<li><a href="">お知らせ</a></li>
<li><a href="">よくある質問</a></li>
<li><a href="">お問い合わせ・手続き</a></li>
</ol>
</header>
Javascriptを解説
カラム落ちを追跡するための関数を作成します。
function checkColumnDrop() {}
function checkColumnDrop() {}
function checkColumnDrop() {}
ハンドリング用にクラス名を付与した要素を取得します。
const columnCheck = document.querySelector('.column_check');
const columnCheck = document.querySelector('.column_check');
const columnCheck = document.querySelector('.column_check');
コンテナ内の子要素を配列として取得します。
const children = Array.from(columnCheck.children);
const children = Array.from(columnCheck.children);
const children = Array.from(columnCheck.children);
カラム落ちの判断を行ううえで基準となる要素は一番左の配列の0番目を取得します。
const referenceElement = children[0];
const referenceElement = children[0];
const referenceElement = children[0];
ブラウザの上部から基準となる要素の下位置を取得します。
const referenceBottom = referenceElement.offsetTop + referenceElement.offsetHeight;
const referenceBottom = referenceElement.offsetTop + referenceElement.offsetHeight;
const referenceBottom = referenceElement.offsetTop + referenceElement.offsetHeight;
カラム落ちが発生した際にトリガーとなる要素に『false』を入れておきます。これ変数には後の処理でカラム落ちが発生した際には『true』を返させて処理を実行させる役割を持たせます。
2番目以降の要素をループさせてカラム落ちをチェックします。
for文の中の処理はループさせた2番目以降の子要素の下位置を比較して基準となる要素を上回った場合にカラム落ち検出済みのフラグを設定、trueを代入します。
for (let i = 1; i < children.length; i++) {
const child = children[i];
// 子要素が基準要素(<h1>)の下端位置より下に配置されている場合、カラム落ちと判断
if (child.offsetTop > referenceBottom && !child.dataset.dropped) {
child.dataset.dropped = "true"; // カラム落ち検出済みのフラグを設定
columnDropped = true; // カラム落ちが発生したことをマーク
for (let i = 1; i < children.length; i++) {
const child = children[i];
// 子要素が基準要素(<h1>)の下端位置より下に配置されている場合、カラム落ちと判断
if (child.offsetTop > referenceBottom && !child.dataset.dropped) {
child.dataset.dropped = "true"; // カラム落ち検出済みのフラグを設定
columnDropped = true; // カラム落ちが発生したことをマーク
}
}
for (let i = 1; i < children.length; i++) {
const child = children[i];
// 子要素が基準要素(<h1>)の下端位置より下に配置されている場合、カラム落ちと判断
if (child.offsetTop > referenceBottom && !child.dataset.dropped) {
child.dataset.dropped = "true"; // カラム落ち検出済みのフラグを設定
columnDropped = true; // カラム落ちが発生したことをマーク
}
}
カラム落ちした際には以下のif文内に行いたい処理を書きます。以下ではアラートを出しています。
if (columnDropped) {
alert('カラム落ちしました!');
//ここに処理を書く
}
if (columnDropped) {
alert('カラム落ちしました!');
//ここに処理を書く
}
カラム落ちしていない場合は以下でフラグをリセットします。
children.forEach(child => delete child.dataset.dropped);
if (!columnDropped) {
children.forEach(child => delete child.dataset.dropped);
}
if (!columnDropped) {
children.forEach(child => delete child.dataset.dropped);
}
以下はページの読み込み時とウインドウのリサイズ時に関数を実行させます。
document.addEventListener('DOMContentLoaded', checkColumnDrop);
window.addEventListener('resize', checkColumnDrop);
document.addEventListener('DOMContentLoaded', checkColumnDrop);
window.addEventListener('resize', checkColumnDrop);
document.addEventListener('DOMContentLoaded', checkColumnDrop);
window.addEventListener('resize', checkColumnDrop);
まとめ
以上、『レスポンシブ下におけるカラム落ちを検知してJavascriptで処理を実行する方法』でした。
動的サイトにおけるコンテンツの増加はレイアウト崩れを誘発しますので頻繁にレイアウト崩れが発生する場合はぜひ参考にしてください。