高さが可変の要素をスクロール対象にする

タイトルだとわかりにくいですが、例えばモーダルコンテンツの中の一部だけ内容量に合わせてスクロールさせる、といった実装をしようとして試行錯誤することがあったので実装方法をメモ。

サンプルコード

まずは対応前のサンプルです。
コンテンツ内の一部がスクロールするモーダルを用意します。

<button data-dialog-link="dialog">dialog</button>

<dialog class="dialog" data-dialog-main="dialog">
  <div class="dialog_content">
    <div class="dialog_head">
      <h3 class="dialog_ttl">dialogタイトル</h3>
      <p class="dialog_description">説明文テキスト</p>
    </div>
    <div class="dialog_scroll">
      <p>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容<br>dialogの内容</p>
      ~略~
    </div>
    <div class="dialog_foot">
      <button class="dialog_close" data-dialog-close="dialog">dialogを閉じる</button>
    </div>
  </div>
</dialog>

.dialog_scrollがスクロールする想定の要素です。

次にJavaScriptでモーダルの開閉処理を追加します。

const dataDialogMain = 'data-dialog-main';
const dataDialogLink = 'data-dialog-link';
const dataDialogClose = 'data-dialog-close';

const $dialogLinks = document.querySelectorAll(`[${dataDialogLink}]`);
const $dialogCloses = document.querySelectorAll(`[${dataDialogClose}]`);

// ダイアログリンククリック時
$dialogLinks.forEach(function(element) {
  element.addEventListener('click', function(e) {
    e.preventDefault();
    const dialogId = element.getAttribute(`${dataDialogLink}`);
    const $dialog = document.querySelector(`[${dataDialogMain} = ${dialogId}]`);
    if($dialog) $dialog.showModal();
  });
});

// 閉じるボタンクリック時
$dialogCloses.forEach(function(element) {
  element.addEventListener('click', function(e) {
    e.preventDefault();
    const dialogId = element.getAttribute(`${dataDialogClose}`);
    const $dialog = document.querySelector(`[${dataDialogMain} = ${dialogId}]`);
    if($dialog) $dialog.close();
  });
});

最後にCSSの設定です。

.dialog {
  inset: unset;
  max-width: unset;
  max-height: unset;
  overflow: unset;
  border: none;
  padding: 0;
  background: none;

  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100dvh;
}
.dialog:not([open]) {
  display: none !important;
}
.dialog::backdrop {
  background: rgba(0, 0, 0, 0.7);
}
.dialog_content {
  max-width: 1200px;
  width: 90%;
  max-height: 90dvh;
  padding: 20px;
  background: white;
}
.dialog_scroll {
  overflow-y: auto;
  padding: 20px;
}

モーダル自体は画面高さの90%を最大高さとして設定して、モーダルの中身はスクロールエリアとテキストのエリアがあり、テキストのエリアはテキスト量に応じて高さが変わります。
そのため、スクロールエリアに任意の高さを設定できず、コンテンツがはみ出して表示されます。
対応前のデモページ

対応方法としてはflexboxを使い、モーダル内の要素を縦積みにします。

.dialog {
  inset: unset;
  max-width: unset;
  max-height: unset;
  overflow: unset;
  border: none;
  padding: 0;
  background: none;

  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100dvh;
}
.dialog:not([open]) {
  display: none !important;
}
.dialog::backdrop {
  background: rgba(0, 0, 0, 0.7);
}
.dialog_content {
  display: flex;
  flex-direction: column;
  max-width: 1200px;
  width: 90%;
  max-height: 90dvh;
  padding: 20px;
  background: white;
}
.dialog_scroll {
  overflow-y: auto;
  padding: 20px;
}

対応後のデモページ

今回はモーダルの最大高さを90%にした上で高さは内容量に合わせて可変にしていましたが、高さを設定(90%)した上でスクロールエリアを引き延ばしたい場合はflex-growを指定します。

.dialog {
  inset: unset;
  max-width: unset;
  max-height: unset;
  overflow: unset;
  border: none;
  padding: 0;
  background: none;

  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100dvh;
}
.dialog:not([open]) {
  display: none !important;
}
.dialog::backdrop {
  background: rgba(0, 0, 0, 0.7);
}
.dialog_content {
  display: flex;
  flex-direction: column;
  max-width: 1200px;
  width: 90%;
  height: 90dvh;
  padding: 20px;
  background: white;
}
.dialog_scroll {
  flex-grow: 1;
  overflow-y: auto;
  padding: 20px;
}

対応後のデモページ2

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2025年11月
 1
2345678
9101112131415
16171819202122
23242526272829
30