ポップアップ


Popover

  • 最上位レイヤーに表示される要素のアニメーション
  • DOM階層や”z-index”の制約を受けない
  • close、::backdrop クリックで閉じる
  • @starting-style で動きを制御

popover属性を使ったモーダル closeボタン、Escキー、領域外クリックで閉じる

HTML

<div class="popover_wrap">
  <button popovertarget="Modal">Open Popover</button>
  <div id="Modal" popover>. // popover宣言
   <p>popover属性を使ったモーダルEscキー、領域外クリックで閉じる</p>
   // <button class="Close" popovertarget="Modal" popovertargetaction="hidden">close</button> // closeボタン追加時
  </div>
</div>

CSS

.popover_wrap {
  & button {
    transition-duration: 0.5s;
    background: rgb(119, 193, 201);
    border-radius: 1rem;
    &:hover,
    &:focus {
      filter: invert();
    }
  }
  & [popover] {
    background: rgba(0, 0, 0, 0.7);
    color: #fff;
    top: 2rem;
    margin-inline: auto;
  }
  & ::backdrop {
    background: rgba(0, 0, 0, 0.2);
    transition: opacity 1s ease;
  }
}

// 背景をスクロールさせない //
html:has([popover]:popover-open) {
  overflow: hidden;
}

[popover]:popover-open {
  translate: 0 0;
}
[popover] {
  transition: translate 0.5s ease-out, display 0.5s ease-out allow-discrete, overlay 0.7s ease-out allow-discrete;
  translate: -10vw 0;
}

// display: none スタートではないトランジション開始時を定義するアットルール //
@starting-style {
  [popover]:popover-open {
    translate: 10vw 0;
  }
}

ダイアログ

  • showModal()など、基本jsと併用。formの戻り値にも対応
  • close、::backdrop クリックで閉じる
  • @starting-style で動きを制御

ダイアログの中身

HTML

<button id="openBtn">dialog open</button>
  <dialog id="myDialog">
    <div class="inner">
    <p>ダイアログの中身</p>
    <button id="closeBtn">close</button>
  </div>
</dialog>

CSS

#openBtn {
  transition-duration: 0.5s;
  background: rgb(142, 179, 152);
  &:hover {
    filter: invert();
  }
}

html:has(#myDialog[open]) {
  overflow: hidden;
  pointer-events: none;
}

#myDialog {
  opacity: 0;
  transform: translateY(1em);
  transition: opacity 0.5s ease, transform 0.3s ease;
  border: #999 solid 1px;
  border-radius: 10px;
  padding: 0;
  filter: drop-shadow(0 0 7px #00000055);
  pointer-events: none; // アニメーション中にクリックされないように //

  &[open] {
    opacity: 1;
    @starting-style {
      opacity: 0;
    }
  }

  &::backdrop {
    opacity: 0;
    background: rgba(100, 0, 0, 0.4);
    transition: opacity 1s;
  }

  &[open]::backdrop {
    opacity: 1;
    @starting-style {
      opacity: 0;
    }
  }
  &.show {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  & #closeBtn {
    margin-block: 1em 0;
    background: #333;
    color: #fff;
    outline: none;
    letter-spacing: 0.1em;
    display: block;
    margin-left: auto;
    &:hover {
      filter: invert();
    }
  }
}

JS

const dialog = document.getElementById("myDialog");
const openBtn = document.getElementById("openBtn");
const closeBtn = document.getElementById("closeBtn");

openBtn.addEventListener("click", () => {
  dialog.showModal();
  requestAnimationFrame(() => {
    dialog.classList.add("show");
  });
});

closeBtn.addEventListener("click", () => {
  closeDialog();
});

dialog.addEventListener("click", (e) => {
  if (e.target === dialog) {
    closeDialog();
  }
});

function closeDialog() {
  dialog.classList.remove("show");
  dialog.addEventListener(
    "transitionend",
    () => {
      dialog.close();
    },
    { once: true }
  );
}

@starting-style

  • アニメーション化させる要素に対して開始時(開く前)のスタイルを設定するアットルール
  • display:none;からのフェードイン・フェードアウトが可能
  • visibility: hidden;、opacity:0; だと表示は消えてもクリック領域などが残る場合の対策に

プロパティ名 | 再生時間 | イージング関数 | 待ち時間 例 : transition: display 4s ease-out 1s
プロパティ名 | 再生時間 | 振る舞い(allow-discrete / normal)例 : transition: display 4s allow-discrete

Dialog

Dialogエリア jsを使えば背景クリックでも終了

HTML

<div class="dia">
  <dialog>
    <p>Dialogエリア jsを使えば背景クリックでも終了</p>
    <form method="dialog">
      <button>Closed</button>
    </form>
  </dialog>
  <button onclick="document.querySelector('dialog').showModal()">Open Dialog</button>
</div>

CSS

.dia {
  & dialog[open] {
    translate: 0 0;
    transition: translate 0.7s ease-out, display 0.7s ease-out allow-discrete;
    @starting-style {
      translate: 0 100vh;
    }
    &::backdrop {
      background: rgba(79, 77, 200, 0.3);
    }
  }
}
CSS

前の記事

コンテナクエリ(@container)
CSS

次の記事

要素の高さを揃える