サイト内の別ページへの切り替え時にフェードイン/フェードアウトなどのエフェクトを施してくれるJavascriptやjQueryプラグインはいくつかあります。
例えば、以下のようなもの。
また、「PJAX」というjQueryプラグインを利用すると、非同期通信でウェブページ内の更新が必要な特定の範囲だけリンク先の別ページの対象コンテンツに置き換えて表示することで、ヘッダーエリアやサイドバー、フッターなどの重複するコンテンツは表示したままにして通信量を減らし、ページ遷移を高速にすることもできます。
さらに、このPJAXを利用してページ遷移効果の実装をより扱いやすくした「Barba.js」という軽量なプラグインもあります。
これらの素敵なプラグインを活用して、新しいインタラクティブなWordPressテーマを作ろうと企画したのですが、開発中のテーマではあらゆる機能やエフェクトのためのスクリプトを読み込んでいたり、ページごとにウィジェットの表示制御や1カラム表示などを指定していた場合など複雑なページ構成を実現できるため、PJAXによる範囲を指定したページ更新に不具合が発生したり、どうしても無理がでてきてしまうため、泣く泣く採用は取りやめにしました。
※PJAXは、とても有用なので、また別のテーマとして採用してみたいと思います。
前置きが長くなりましたが、PJAXが採用できなくなったため、せめてページ遷移時にフェードイン・アウト効果をプラグインを利用せずに、少しのコードで簡単に実装する方法を考えてみました。
まずはデモをご覧ください!
ページ遷移エフェクトの仕組み
今回のサンプルによるページ遷移時のフェードイン・アウトの仕組みをざっくり説明すると、body
要素の::after
疑似セレクタをページ全体を覆う一番手前のレイヤーとしてCSSでスタイリングし、ページが表示されたときはこのレイヤーの不透明度(opacity
)は「100%」から「0%」にフェードアウトし、アンカー(a)タグをクリックしてページが遷移するときは、レイヤーの不透明度を再び「0%」から「100%」にフェードインした直後に遷移させています。
HTMLの構造
フェードイン・アウト効果は、ページ全体を覆うレイヤーとなる、body
要素の::after
疑似セレクタの透過有無をアニメーションさせることで表現しています。
body
要素に.fadeout
というセレクタを付けておき、このセレクタがある場合はページ全体がフェードアウト(レイヤー表示中)している状態にします。
<!-- .fadeoutがあるときはフェードアウト --> <body class="fadeout"> : </body>
body
要素内のHTMLは何でもいいのですが、同一サイト内へのリンクを適当に配置します。
<a href="two.html" class="navigate-anchor">Move to Next Page</a>
今回のサンプルでは、全体としては以下のようなシンプルなHTML構造にしています。
<body class="fadeout"> <section class="page one"> <article> <h1>Page One</h1> <a href="two.html" class="navigate-anchor">Move to Next Page</a> </article> </section> </body>
CSSの構成
レイヤーとなるbody
要素の::after
疑似セレクタは、以下のようにしてページ全体を覆うようにしています。
ポイントは、他のどの要素よりも手前に来るように、z-index
で重なりを指定すると同時に、pointer-events:none
としてページ内の要素へのアクセスに支障がないようにこのレイヤー自体のポインターイベントは無効にします。
body::after { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color:#fff; /* 背景カラー */ z-index: 9999; /* 一番手前に */ pointer-events: none; /* 他の要素にアクセス可能にするためにポインターイベントは無効に */ opacity: 0; /* 初期値 : 透過状態 */ -webkit-transition: opacity .8s ease; /* アニメーション時間は 0.8秒 */ transition: opacity .8s ease; }
body
要素に .fadeout
セレクタがある場合に、このレイヤーが表示されるよう、opacity
を1にします。
body.fadeout::after { opacity: 1; }
ページ遷移のフェードイン、フェードアウトに関するCSSはたったこれだけです。
後は、お好みで.fadeout
セレクタの有無で他の要素にもアニメーション用のCSSを定義してください。
例えば、今回のデモではページ遷移時にarticle
要素のスケールもアニメーションさせています。
body.fadeout article{ -webkit-transform:scale(1.2); transform:scale(1.2); }
Javascript(jQuery)の構造
jQueryを利用しているので、まずはjQueryを読み込んでおきましょう。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" crossorigin="anonymous"></script>
まず、ページ表示時にはレイヤーを非表示にするため、body
要素から.fadeout
セレクタを取り除きます。
$(window).on('load', function(){ $('body').removeClass('fadeout'); });
そして、ページ内のアンカータグがクリックされたときはそれを検知して、HTMLの通常のページナビゲート動作を一旦無効化し、body
要素に再び.fadeout
セレクタを追加してページ全体をフェードアウトさせてから、アニメーション時間経過後にクリックされたアンカータグのhref属性に指定されたURLに遷移します。
$(function() { // ハッシュリンク(#)と別ウィンドウでページを開く場合はスルー $('a:not([href^="#"]):not([target])').on('click', function(e){ e.preventDefault(); // ナビゲートをキャンセル url = $(this).attr('href'); // 遷移先のURLを取得 if (url !== '') { $('body').addClass('fadeout'); // bodyに class="fadeout"を挿入 setTimeout(function(){ window.location = url; // 0.8秒後に取得したURLに遷移 }, 800); } return false; }); });
ポイントは、アンカータグのクリックの検出は、a:not([href^="#"]):not([target])
としてハッシュリンク(#)とtarget=”_blank”などとして新しいウィンドウでURLを参照する場合は除外することと、setTimeout
で待機する時間は、CSSのtransition
で指定したアニメーション時間と同じにしておくことです。
以上、たったこれだけでページ遷移時のフェードイン・アウト効果が表現できました。