いくつかの特徴的な機能について、仕組みを簡単に説明します。

別ページへのリンクでスムーススクロールを行う仕組み

ハッシュタグ付きの別ページへのリンクをクリックした場合、通常は、jQueryでスクロールさせる前に、そのidがついた要素の部分へジャンプして表示されてしまいます。ですので、それを回避し、ページの最上部が表示された後に該当箇所へスクロールさせる手順が必要となります。

この実現方法として、ハッシュタグ付きの別ページへのリンクをクリックした場合、ハッシュタグ(例えば #link )を ?scroll_id=link に変換します。この変換は、条件に該当するリンクをクリックしたタイミングで行われます。

例えば、リンクのhrefが page.html#link なら、 page.html?page_id=link に変換してリクエストを送ります。この方法で、ページ遷移直後にid要素にジャンプすることを回避することができます。

その後、URL内の page_id=link をもとに、idが link の要素を探し、その部分までスクロールをさせる、といった流れで、他ページリンクのスクロールを実現しています。

また、もともとhrefに他のクエリパラメータが付いている場合も考慮されています。例えばhrefが /dir/page.html?key=value#link なら、 /dir/page.html?key=value&scroll_id=link に変換されます。

ページ内リンク、サイト内別ページリンク、別サイトリンクの判別方法

ハッシュ(#)が含まれるリンクを3種類に判別し、それぞれ動作を変更させています。

  • ページ内リンクである
  • サイト内の別ページへのリンクである
  • 別サイトへのリンクである

まず、ハッシュ(#)ではじまるリンクの場合、無条件で通常のページ内スクロールを行います。

次に、ハッシュ以外ではじまるハッシュを含んだリンク(例えば /dir/test.html#link )について、いくつかの判別を行います。

まず、リンクがサイト内へのリンクか別サイトへのリンクかの判定を行います。別サイトへのリンクの場合は、何も行いません。

同サイトへのリンクの場合、次にページ内リンクであるかどうかの判定を行います。

「同じページへのリンクである」という判断基準

「同じページへのリンクである」、つまりページ内リンクであることの基準は、ブラウザデフォルトの挙動に準じます。つまり、デフォルトの挙動でページ遷移(再読込)が行われないリンクの場合、「同じページ」と判断します。

以下は、同じページへのリンクの例です。

ページURL: http://example.com/test/index.html の場合
  • #(ページのトップへスクロール)
  • #link
  • /test/index.html#link
  • http://example.com/test/index.html#link

index.html の省略の有無やクエリパラメータが異なる場合は、ブラウザデフォルトの挙動と同じく別ページと判定されます。

ただし、URLのスクロールキーとその値(scroll_id=xxx )は判別に影響しません。

URLが http://example.com/?scroll_id=test の場合、 http://example.com/#link は同じページとして扱われ、ページ遷移のないスムーズスクロールが行われます。

同じページと判別された場合、通常のスムーススクロールを行います。別ページと判別された場合、リンク先URLを変換したのちにページ遷移し、その後スクロールが行われます。

URL書き換えの仕組み

スムーススクロールを実現するにあたり、通常 event.preventDefault() で初期動作を無効化するため、URLにハッシュタグが表示されません。

しかし、ページ内スクロールしたらちゃんとハッシュタグつけたい!という声もあるかと思います。そんなご要望にお応えして、smooziee.jsでは、スクロールされた後に、 window.history.pushState を使って、URLをハッシュタグ付きのURLに書き換えています。

また、他ページへのリンク時に scroll_id=xx が表示されたままなのもなんかアレだ。というわけで、この場合も、変換される前の元のハッシュタグに書き換えをします。一瞬、URLがページリダイレクトみたいな挙動を見せるのはそのためです。

URL書き換えは、設定によって無効にできます。また、従来のスムーススクロールのように、URLにハッシュタグがつかないようにすることもできます。