作成日:2022-09-08
前回目次機能は追加したが、目次クリックでその場所まで移動させる機能が欲しかったので、実装しました。何とかcssだけで解決したかったけどできず、javascriptに頼るしかなかった。
目次をクリックして、その見出しへ移動して欲しい。
単純に見出しidに対しての#リンクを使用すればできる。前回の設定で色々していたため、かなり簡単な作業だった。
前回の目次の追加はこちら
marginとpaddingで相殺すればできるようなのでやってみたが。
h1 {
display:block;
margin-top:22px;
padding-top:22px;
}
上記で解決できるのだが、私の場合見出しにすでにデザインのためのmarginとpaddingが入ってしまっている。afterやbeforeを使って見たがデザインを崩さずに位置調整をすることができなかった。
今の私のブログだと見出しが隠れてしまうので正直javascriptを使うのが面倒だと思って使いたくなかった。 できればcssだけで解決できればありがたいと思ってましたが、どうしてもcssだけで解決できなかったので、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) <--追加
javascriptで実装したので<a>
タグではなくなりました。
リンクではなく通常の文字のため黒い文字、カーソル当てても何も変化がない。ユーザーに優しくないリンクになっています。それをcssでユーザーに優しい見た目にします。
tags:hover {
cursor: pointer;
color: blue;
text-decoration: underline;
}
カーソルホバー時にテキストの色、アンダーライン、カーソルの形の変化を追加しました。
コード内容はとても単純でidでエレメントを取得し、そのtop値+調整する値を入れた。
cssだけでどうにかしようと考えたことが間違いでした。デザインの制限が発生してしまいます。 javascriptでの実装はとても簡単にできてしまった(4行程度)。cssで模索するのではなく素直にjavscriptを使っていれば良かったなと思います。
また、プラグインgatsby-remark-table-of-contents
を使わないで正解でした。使うとジャンプ位置の微調整はできなかったと思います。
質問や、間違いがありましたら、お気軽にどうぞ
※お名前とコメントの内容を入力してください。
※全てこのブログ上に公表されます。
※許可なく管理者によって修正・削除する場合がございます。 詳しくはプライバシーポリシーを参照ください