Hero img
Gatsby タイトルにジャンプ

目次クリックでタイトルの位置に移動

前回目次機能は追加したが、目次クリックでその場所まで移動させる機能が欲しかったので、実装しました。何とかcssだけで解決したかったけどできず、javascriptに頼るしかなかった。


目次

  • 目次にcssで
  • cssでの解決方法
  • cssだけではできなかった
  • javascriptで移動させる。
  • 移動させる
  • 前回のソース
  • cssで整える
  • まとめ

目次にcssで

目次をクリックして、その見出しへ移動して欲しい。
単純に見出しidに対しての#リンクを使用すればできる。前回の設定で色々していたため、かなり簡単な作業だった。 前回の目次の追加はこちら

cssでの解決方法

marginとpaddingで相殺すればできるようなのでやってみたが。

h1 {
display:block;
margin-top:22px;
padding-top:22px;
}

上記で解決できるのだが、私の場合見出しにすでにデザインのためのmarginとpaddingが入ってしまっている。afterやbeforeを使って見たがデザインを崩さずに位置調整をすることができなかった。

cssだけではできなかった

今の私のブログだと見出しが隠れてしまうので正直javascriptを使うのが面倒だと思って使いたくなかった。 できればcssだけで解決できればありがたいと思ってましたが、どうしてもcssだけで解決できなかったので、javascriptを使うことにした。

javascriptで移動させる。

javascriptで特定位置まで移動するためには、window.scrollToとwindow.scrollがあるらしい。 両方試したうえで、window.scrollの方が扱いやすかったので、window.scrollを使っていく。

移動させる

それでは実際にwindow.scrollを使ってみる
私の場合クリックしたら移動してほしいのでクリックイベントを作成した。

const TOCclickEvent = ((elementid) => {
    let targetelement = document.getElementById(elementid.slice(1));
    window.scroll({
        top: targetelement.offsetTop - 22,
        behavior: "smooth"
    });
});

elementid.slice(1)が謎の処理になってスマートではないが、 gatsby-remark-autolink-headersを既に導入しているためそgraphqlのtableOfContentsからidを取得したためだ。 別の方法も色々とやってみたのだが、大文字、小文字、記号,スペース文字、重複等があった場合gatsby-remark-autolink-headersが自動的id変換し割り当てを処理しているので。このようなコードになってしまった。

前回のソース

実際に前回のソースにonClickEventを追加した。

export const PostPagesMain = (props) => {
    const indexlist = props.data.mdx.tableOfContents;

    function returnvalues(obj) {//再起関数
        return <li>
            <span onClick={(() => { OnclickEvent(obj.url) })}>
                {obj.title}
            </span>
            <ul>
                {obj.items && obj.items.map(index =>
                    returnvalues(index))
                }
            </ul>
        </li>
    }

    return (
        <div>
            <h4>目次</h4>
            <ul>
                {indexlist.items.map(items => returnvalues(items))
                }
            </ul>
        </div>
    )
}

export const pageQuery = graphql`
query BlogPostQuery($id: String) {
  mdx(id: { eq: $id }) {  
    body
    slug
    tableOfContents(maxDepth: 3) <--追加

cssで整える

javascriptで実装したので<a>タグではなくなりました。 リンクではなく通常の文字のため黒い文字、カーソル当てても何も変化がない。ユーザーに優しくないリンクになっています。それをcssでユーザーに優しい見た目にします。

tags:hover {
cursor: pointer;
color: blue;
text-decoration: underline;
}

カーソルホバー時にテキストの色、アンダーライン、カーソルの形の変化を追加しました。

コード内容はとても単純でidでエレメントを取得し、そのtop値+調整する値を入れた。

まとめ

cssだけでどうにかしようと考えたことが間違いでした。デザインの制限が発生してしまいます。 javascriptでの実装はとても簡単にできてしまった(4行程度)。cssで模索するのではなく素直にjavscriptを使っていれば良かったなと思います。 また、プラグインgatsby-remark-table-of-contentsを使わないで正解でした。使うとジャンプ位置の微調整はできなかったと思います。

関連記事

コメント

コメントを書く

質問や、間違いがありましたら、お気軽にどうぞ

※お名前とコメントの内容を入力してください。
※全てこのブログ上に公表されます。
※許可なく管理者によって修正・削除する場合がございます。 詳しくはプライバシーポリシーを参照ください