モーダルウィンドウ風UI(with Fragment Plugin)
モーダルウィンドウ風UIの実装では画面上のさらに特定の部分(fragment)だけのコンテンツの差し替えを実行するために、前述したFragment pluginを利用します。
swup.jsを使ったモーダルの実装ではURLが変化するため、開いた詳細画面をSNS等で共有可能にしたいケースなどで有用で、ブラウザの標準操作が生きるので自然に操作できるページになり、UXの向上が見込まれます。また、ページ数が増え、検索エンジンに通常ページとしてクロール・インデックスされるのでSEO対策にも効果が見込めるかと思われます。
Fragment pluginは、今回取り扱うモーダルのようなページ遷移の他、フィルターを使ったコンテンツの切り替えや絞り込み時に、一覧部分の表示を切り替えるというようなケースでも利用できます。
利用方法は、簡単にまとめると以下の4ステップです。
- CDNでプラグインを読み込む
- モーダルが開いた後のページを実装(この時、背景になるコンテンツもそのまま存在するようにする)
- モーダルが開く前のページにプレースホルダーとしてtemplate要素を追加
- swup.jsにオプションを指定
まずは基本で読み込んだコアのJSファイルの後にプラグインを読み込みます
<script src="https://unpkg.com/swup@4"></script>
<script src="https://unpkg.com/@swup/fragment-plugin@1"></script><!-- プラグインファイル -->
次に「モーダルが開いた後のページを実装」ですが、モーダルウィンドウの開閉に関するJSの実装などは無視して構わないので、モーダルを開いた後のUI(公式ではdialog要素を使うことを推奨)を実装します。
この時、Fragment Pluginを使った遷移では対象部分(モーダル・リストなど)のみを再描画するため、背景になるコンテンツも遷移後のページに必要なのでその点は注意してください。
HTML
<dialog class="modal" id="modal" open>
<div class="modal__inner">
<a href="index.html" class="modal__close">×</a>
<img src="./dummy.jpg" alt="" class="modal__image">
<div class="modal__text">
<h2 class="modal__title">モーダル風画面</h2>
<p>モーダル風画面の中身</p>
</div>
</div>
</dialog>
/* モーダル用スタイル */
.modal {
border: none;
background-color: transparent;
margin: auto;
}
.modal__inner {
background: #fff;
padding: 0;
border-radius: 16px;
width: min(90vw, 500px);
box-shadow: 0 2px 16px rgba(0,0,0,0.2);
position: relative;
font-size: 14px;
font-weight: 400;
overflow: hidden;
}
.modal::backdrop {
background: rgba(0, 0, 0, 0.5);
}
.modal__close {
position: absolute;
top: 10px;
right: 10px;
text-decoration: none;
background: none;
border: none;
font-size: 30px;
cursor: pointer;
color: #000;
border-radius: 100vmax;
width: 40px;
height: 40px;
background-color: #333;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
transition: ease 300ms;
}
.modal__close:hover {
background-color: #555;
}
.modal__text {
padding: 1em 2em 2em;
}
.modal__title {
font-size: 24px;
font-weight: 600;
margin-bottom: 0.5em;
}
.modal__image {
aspect-ratio: 16/9;
object-fit: cover;
object-position: 50% 65%;
width: 100%;
height: auto;
margin: 0;
padding: 0;
}
次にモーダルを開く前のページにtemplate要素を追加します。
swup.jsの基本的な実装ケースでは
遷移開始アニメーション開始 → 遷移開始アニメーション終了 → コンテンツ切り替え → 遷移終了アニメーション開始 → 遷移終了アニメーション終了
というようなライフサイクルをとるのですが、モーダルの場合差し代わるコンテンツが存在しないため、コンテンツ切り替え前後の片方のアニメーションが丸ごと不要で、そのようなケースではtemplateを使ったプレースホルダーを用意してあげることで対応ができます。
※この時、要素の入れ子関係に注意してください。基本のswupコンテナの中身にtemplate要素が入るようにします。
<main id="swup" class="transition-main">
<template id="modal"></template>
<!-- 差し代わるコンテンツが入ります -->
</main>
最後にswup.jsの初期化時にオプションを指定します。
オプションの指定は遷移前/遷移後のURLルールと切り替わるコンテナーのID(classやネストされたセレクターはエラーになります)で指定します。
※うまくいかない場合はURLルールの指定ミスが怪しいです(経験者談)
// swup初期化
const swup = new Swup({
containers: ['#swup'],
plugins: [
new SwupFragmentPlugin({
rules: [
{
// モーダルウィンドウが開く前がindex.html、開いた後がmodal-open.htmlの場合
from: ['/index.html', '/modal-open.html'],
to: ['/index.html', '/modal-open.html'],
containers: ['#modal'],
}
]
})
]
});