Intersection Observer を使ったアンカーリンクナビ
Intersection Observerを使ったアンカーリンクのナビゲーションを作ってみました。
要素の位置に応じて、ナビゲーションのマーカーが表示される仕組みです。
インターセクションオブザーバーについての解説記事はこちら
サンプルの内容が思いつかなかったのでオススメのPC周りのグッズを紹介しておきます。
WEBカメラ C920n とUSB切替器
ロジクールのWEBカメラC920nを2台のPCで共有するためにUSBスイッチャーを導入した記事です。
USBスイッチャーがあるおかげでUSBの付け替えが不要で楽ちんです。
ロジクールの高機能高級ワイヤレスキーボード CRAFT
ロジクールが出している高級ワイヤレスキーボードCRAFT(KX1000s)。キーストロークが浅めが好みの私にはドンピシャのお気に入りキーボードになりました。
これも2台のPCをボタン1つで切り替えて、共通して使える優れモノ。
フットレストで腰への負担を軽減しよう
イスに座った状態で足を伸ばすと、地面に接地する距離が少し遠く、太ももや腰に負担がかかるのでフットレストを導入しました。
あぐら姿勢で仕事することが多かったのですが、フットレストを導入してから少し姿勢が良くなった気がします。
HUAWEI ウルトラワイドモニター MateView GT
でかいモニターに慣れるともう小さいモニターでは仕事する気になれません。1画面で得られる情報量は多い方が色々楽です。
ワイドモニターに縦置きのモニターがあれば、完璧な作業環境が手に入ります。
サイト内のアンカーリンクナビをCSSのstickyで固定して、クリックするとアンカーリンクで移動する仕組みです。
要素に入ったらナビゲーションのラインアニメーションを発動
今回のサンプルはスクロールに応じて、アンカーリンクのナビゲーションのラインが表示されるという仕組みです。
スクロール監視ということで「Intersection Observer」を利用した仕組みになっています。
ナビゲーション部のHTMLソース
ナビゲーションは普通に作られています。
<ul id="unker_nav"> <li><a href="#pos1">オススメ1</a></li> <li><a href="#pos2">オススメ2</a></li> <li><a href="#pos3">オススメ3</a></li> <li><a href="#pos4">オススメ4</a></li> </ul>
監視ターゲットのHTMLソース
こちらは監視要素を共通のクラス「inter_pos」を設定し、data属性を使ってナンバリングをしています。
ナビゲーションのインデックス番号とリンクさせるためのナンバリングです。
<div id="pos1" class="inter_pos" data-num="0"> <h3>pos1</h3> </div> <div id="pos2" class="inter_pos" data-num="1"> <h3>pos2</h3> </div> <div id="pos3" class="inter_pos" data-num="2"> <h3>pos3</h3> </div> <div id="pos4" class="inter_pos" data-num="3"> <h3>pos4</h3> </div>
実際のサンプルソースとは異なりますが、説明に不要な個所は省いています。
Intersection Observerを設定しているJavaScript
インターセクションオブザーバーのスタンダードな使い方になっていますが、今回は監視対象と、クラスを付与する要素が異なります。
交差した要素のdata-numに振られた数値を取得し、その数値をliのインデックスとして利用し、そのliにクラスを付与&削除する仕組みです。
//▼監視対象 const target_item = document.querySelectorAll(".inter_pos"); //▼ナビゲーションのliを取得 const unker_nav = document.querySelectorAll("#unker_nav li"); window.addEventListener("load", (event) => { let vh = document.documentElement.clientHeight; let nav_vh = document.getElementById('unker_nav').clientHeight; let head_vh = document.getElementById('header_box').clientHeight; let fix_vh = nav_vh + head_vh + 20; var zan_vh = vh - fix_vh; createObserver(zan_vh, fix_vh); }, false); function createObserver(zan_vh, fix_vh) { let options = { root: null, rootMargin: "-" + fix_vh + "px 0px -" + zan_vh + "px 0px", threshold: 0 }; let main_observer; main_observer = new IntersectionObserver(nav_set, options); target_item.forEach( (elem) => { main_observer.observe(elem); }); } function nav_set(entries){ entries.forEach(entry => { //▼data-numの取得 let set_num = entry.target.dataset.num if (entry.isIntersecting) { //▼取得したdata-numを使ってアクティブなliにクラス付与 unker_nav[set_num].classList.add("sample_on"); }else{ //▼交差範囲から外れたらクラスを外す unker_nav[set_num].classList.remove("sample_on"); } }); }
ナビの当たり判定を可能な限り正確にしたくて、ごちゃごちゃと色々やってます。
11行目~16行目です。
JavaScriptで各要素の高さを取得して、計算して出しています。
適切なrootMarginの求め方
rootMarginの調整で、交差範囲をアンカーナビのところに持ってくるのに苦労しました。
色々と試行錯誤してこの形になりました。
最初はざっくりと-80%とかで設定していたんですが、ウィンドウサイズを変更すると交差範囲がずれるのが気に入らなくて、なるたけ厳密に求めるようにしました。
これが正しいかどうかは不明ですが、とりあえず納得できる動きになりました。
JavaScriptを使ってそれぞれの要素の高さを取得し、関数の引数にあてて適用してます。
もっとちゃんとやるとしたら、閲覧中にウィンドウサイズが変更された際に、全ての高さを再取得する必要があります。
そこまではいいかなと思ってやってません。
CSSアニメーションで動きをつける
メインのJavaScriptの解説は終わったので、CSSを簡単に紹介して終わりたいと思います。
#unker_nav { display: flex; width: 100%; justify-content: space-between; position: sticky; z-index: 1; top: 70px; background: rgba(0,0,0,0.8); padding-bottom: 4px; } #unker_nav li{ width: 24.5%; text-align: center; transition: all 0.3s 0s ease; } #unker_nav li a{ display: block; padding: 4px 0; color: #fff; box-sizing: border-box; } #unker_nav li:hover{ background: #000; opacity: 0.8; } .sample_on{ background: #000; position: relative; } .sample_on::after { content: ''; position: absolute; left: 0; bottom: 0; border-bottom: solid 3px #c00; animation: border_anim 0.2s ease-in forwards; } @keyframes border_anim { 0% { width: 0%; } 30% { width: 50%; } 100% { width: 100%; } } @media screen and (max-width: 640px){ #unker_nav { top:41.5px; } }
#unker_navを 「postion: sticky;」 で固定しています。
44行目の「@keyframes border_anim」でアニメーション効果を作って、交差した時にラインアニメーションを適用しています。
その他は主にレイアウトのCSSですね。
※関係なスタイルは省いています。
Intersection Observer を使ったアンカーリンクナビ まとめ
今回のナビゲーションも前回に引き続き、仕事で使ったんですが、交差範囲の設定が甘くてもうちょっと完成度を高めたかったのですが、納期の都合で許容範囲までしか詰め切れず。
というわけで、インターセクションオブザーバーの使用例も兼ねて、研究してみました。
アンカーナビのアニメーションとアクティブ判定がいらなければ、交差監視は不要です。
だけど、ちょっとした遊び心とユーザビリティを加えたくなるじゃないですか。
こういう売上や成果に直結するとは言い難い、パーツや動き、仕組みなんかをどれだけ持っているかを私は結構大事にしています。
仕事で詰め切れないことを自分のサイトで突き詰めて、次に仕事に生かすと。
またインターセクションオブザーバーを使って、なにかを作りたいとおもいます!