astro-notion-blogで現在地がハイライトされる目次を作ろうと弄り始めたのですが、その過程で見出しのカスタマイズの寄り道がしたくなりました。
GitHubのREADMEやZenn、Qiitaの見出しはマウスホバーでアンカーリンクのアイコンが左に現れます。これにはリンクが埋め込まれていて、ドラッグアンドドロップでブックマークに追加すると、そのページのその見出しに対して直接ジャンプできるようになります。右クリックからリンクのコピーもできます。他の使い方は知りません。
![Image in a image block](/notion/c1926c9c-2970-471a-953b-7f74cb19ca56/GitHub%E3%83%9B%E3%83%90%E3%83%BC%E8%A6%8B%E5%87%BA%E3%81%97.gif)
![Image in a image block](/notion/40094fdb-052d-4ee2-8158-0c9f3563b6e8/Zenn%E3%83%9B%E3%83%90%E3%83%BC%E8%A6%8B%E5%87%BA%E3%81%97.gif)
![Image in a image block](/notion/8ad20aa9-e15f-4cdd-9abe-c433b7bb69ca/Qiita%E3%83%9B%E3%83%90%E3%83%BC%E8%A6%8B%E5%87%BA%E3%81%97.gif)
なんとなくかっこいいので作ってみることにしました。
前の記事📄要素が自動配置されるトグルスイッチを作る(CSSのみ・計算不要) で擬似要素の応用を先にやったので、テキストを
::before
で挿入する基本的な方法で作ってみました。
見出しにマウスカーソルが重なると、見出しの左にリンクが埋め込まれた#
が浮かび上がります。クリックすると見出しが画面上端に飛ぶのが確認できます。
#
はテキストとしての#
なので、大きさはフォントサイズに依存します。
また、絵文字を使うこともできます(見た目はあまり良くないです)。
![Image in a image block](/notion/e6a886c9-5599-4421-98ee-54181f8238c5/%E7%B5%B5%E6%96%87%E5%AD%97%E3%83%9B%E3%83%90%E3%83%BC%E8%A6%8B%E5%87%BA%E3%81%97.gif)
かなりシンプルに書けたので満足です。
これが本命です。よく見るやつはSVGでアイコンを設定し、それがマウスホバーで出てきます。
任意の画像で使えなければあまり意味ないですからね。
擬似要素で画像が出たり隠れたりするように作り替えました。
![Image in a image block](/notion/99d6b67c-e99d-4943-b141-48c79fc800dd/%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%83%9B%E3%83%90%E3%83%BC%E8%A6%8B%E5%87%BA%E3%81%97.gif)
CodePenに直リンク貼っても迷惑にならない適当な画像が無かったため、このブログのロゴのSVGファイルを入れておきました。アスペクト比1:1なので見やすいと思います。
擬似要素による領域は赤色部分で、見出しの要素と同じ高さになっています。これを、幅のみwidth
で指定して、そこに収まるようにbackground-size: contain;
とbackground-repeat: no-repeat;
とbackground-position: 0% 50%;
でど真ん中にしてあります。
background-position
プロパティのy方向(2つめ)のパラメータを変更することで、縦方向の調整が可能です。
![Image in a image block](/notion/5acc4635-06b8-4acf-ae40-a8b585ca67ac/Image-0.png)
![Image in a image block](/notion/64fe8830-5185-4abc-97ab-294d4b8423e6/Image-1.png)
![Image in a image block](/notion/c69775bb-df12-4afe-ad80-05c3727aa481/Image-2.png)
0% 50%
は計算上ど真ん中ですが、青色の領域を見れば分かる通り、テキスト本体の偏りでズレて見えるため実際には微調整が必要になります。僕の場合は0% 40%
が丁度いい感じでした。使用するアイコンによっても変わりそうです。
この方法で大抵の画像をアイコンとして設定可能ですが、SVGを使う場合、ダークモード時にCSSから色を変更できないという弱点があります。僕のブログは黒背景か白背景なので灰色にでもしておけばいいんですが、一応方法を探しました。
こちらのサイト(SVGデータをCSSのbackground-image向けのBase64コードにかんたん変換ツール)でSVGデータを直にCSSプロパティとして入力可能にすることで、CSS上で切り替えることができます。(これファイル2つ用意して参照先切り替えるのと同じことですね)
他にはmask-imageを使う方法があるようなんですが、使おうと思っていたSVGアイコンに効かないようだったので一旦保留にしました。色の設定が無い別のSVGアイコンを使えばできたので、適用自体はできそうです。
でもCodePenに貼るためにはSVGを自分で用意する必要がありますね。少し悩みます。
今回のCSSではtranslate: -100%;
を使い、擬似要素を見出しの左端にピッタリ接するように移動しています。これを-110%
などにしてしまうと、要素の間に微小な隙間が生まれてしまいます。
見出しにマウスカーソルを重ね、出現したアイコンに向かってマウスカーソルを移動すると、途中の隙間でホバーを満たさなくなり、アイコンが消えるということがありました。
当たり判定が見出しとの間にも存在するようにするか、他にいい方法があるのか、しばらく考えてみたいです。