2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Modalって作るの難しい・・・諳んじれますか?

Last updated at Posted at 2024-02-28

ふと気になって調べること数十回。自分の中で区切りをつけたいので記事にまとめます!

あと、諳んじる必要は全く無いと思っています!

環境

BrowserがあればOKです。

一応、リポジトリにNode プロジェクトとしても作ってあります。npm run startで動きます。

実装

Modal構成要素

  • ダイアログ中央表示
  • Overlay
  • 表示・非表示切り替え

では、順番に実装していきましょう。

ダイアログ中央表示

絶対位置で、ダイアログを中央に配置します。

index.html
<!DOCTYPE html>
<head>
  <title>Modal App</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <div id="dialog">Dialog</div>
</body>
style.css
#dialog {
  position: fixed; /* 絶対位置で表示 */
  top: 50%; /* 上端を中央に */
  left: 50%; /* 左端を中央に */
  /* 上記までで、エレメント左上が中央に位置することになる*/
  /* 再配置を行うtranslateで、エレメントをその大きさの半分ずつ左と上にずらす*/
  /* これにより、エレメントの中心がWindowの中心に位置することになる。*/
  transform: translate(-50%, -50%);
  width: 30%; 
  height: 30%;
  border: 1px solid black;
  background-color: lightblue;
}

Overlay

ダイアログの背面にシートを敷くイメージです。

index.html
<!DOCTYPE html>
<head>
  <title>Modal App</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <div id="dialog">Dialog</div>
+ <div id="overlay"></div>
</body>
style.css
#dialog {
  position: fixed; /* 絶対位置で表示 */
  top: 50%; /* 上端を中央に */
  left: 50%; /* 左端を中央に */
  /* 上記までで、エレメント左上が中央に位置することになる*/
  /* 再配置を行うtranslateで、エレメントをその大きさの半分ずつ左と上にずらす*/
  /* これにより、エレメントの中心がWindowの中心に位置することになる。*/
+ z-index: 1000; /* 他の要素よりも手前に表示する */
  transform: translate(-50%, -50%);
  width: 30%; 
  height: 30%;
  border: 1px solid black;
  background-color: lightblue;
}

/* 追加 */
#overlay {
  position: fixed; /* 絶対位置で表示 */
  /* 画面全体を覆う */
  /* Browser windowの左上から、縦横一面の大きさを設定し配置*/
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 999; /* 他の要素よりも手前に表示する。ただし、ダイアログの背面 */
  background-color: lightgray;
}

表示・非表示

JavaScriptによる制御を組み込みます

また、ダイアログ表示にちょっとした動きを取り入れます。

index.html
<!DOCTYPE html>
<head>
  <title>Modal App</title>
  <link rel="stylesheet" href="style.css" />
</head>
<body>
  <div id="dialog">Dialog</div>
  <div id="overlay" />
+ <button id="open-button">Open</button>
+ <script src="index.js"></script>
</body>
style.css
#dialog {
+ /* 初期状態では非表示 */
+ opacity: 0; 
+ visibility: hidden; 
+ /* 0.3sかけて、表示・非表示が切り替わります。 */
+ transition: all 0.3s ease-out;
  position: fixed; /* 絶対位置で表示 */
  top: 50%; /* 上端を中央に */
  left: 50%; /* 左端を中央に */
  /* 上記までで、エレメント左上が中央に位置することになる */
  /* 再配置を行うtranslateで、エレメントをその大きさの半分ずつ左と上にずらす */
  /* これにより、エレメントの中心がWindowの中心に位置することになる。*/
  z-index: 1000; /* 他の要素よりも手前に表示する */
  transform: translate(-50%, -50%);
  width: 30%; 
  height: 30%;
  border: 1px solid black;
  background-color: lightblue;
}

#overlay {
+ /* 初期状態では非表示 */
+ /* visibility: hidden;を設定することでOpenボタンを活性にできます。*/
+ opacity: 0; 
+ visibility: hidden; 
+ transition: all 0.3s ease-out;
  position: fixed; /* 絶対位置で表示 */
  /* 画面全体を覆う */
  /* Browser windowの左上から、縦横一面の大きさを設定し配置 */
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 999; /* 他の要素よりも手前に表示する。ただし、ダイアログの背面 */
  background-color: lightgray;
}

/* 追加 */
#open-button {
  cursor: pointer;
  border: 1px solid #000;
  margin: 10px;
}
index.js
// エレメントを取得
const dialog = document.getElementById('dialog');
const overlay = document.getElementById('overlay');
const openButton = document.getElementById('open-button');

// Scrollを固定するためのエレメント
const body = document.body;

// 表示処理
openButton.addEventListener('click', open);
function open() {
  dialog.style.opacity = 1;
  dialog.style.visibility = 'visible';
  overlay.style.opacity = 1;
  overlay.style.visibility = 'visible';
  body.style.overflow = 'hidden';
}

// 非表示処理
overlay.addEventListener('click', close);
function close() {
  dialog.style.opacity = 0;
  dialog.style.visibility = 'hidden';
  overlay.style.opacity = 0;
  overlay.style.visibility = 'hidden';
  body.style.overflow = 'auto';
}

最後に

この仕組みを理解していると、アカウント登録ダイアログがPopupして、続きが見れない系のモーダルを・・・

ということもできてしまいます。

Browser上のリソースは、基本的に見られてしまう・変更できてしまうということは忘れたくないですね。

また、実際のアプリケーションにおいては、"車輪の再発明"は必要ないです。

可能な限りよく使われているライブラリを使用しましょう!

あと、不勉強でしたが、Dialogタグも使えるようになっているようです!

リポジトリ

simple-node-app

2
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?