astro-notion-blogでサイドバーをカスタマイズする

Featured image of the post

目次

まえがき

サイドバーを右へ移動(ホバー表示と干渉するため中止)

src\layouts\Layout.astroの166行目あたりでメインカラムのorderを1に。

177行目あたりでaside(サイドバー)のorderを2に。

フレックスアイテムの表示順序が変更されてサイドバーが右になった。

Image in a image block
ホバーではみ出すのって右側じゃん

大画面だとやたらと左に寄ってしまうし、ホバーもったいないし、中止。

サイドバーの記事名をホバー表示させる(後に記事名を折り返し表示に変更)

書いてある通りにする。

src\components\BlogPostsLink.astro を開き、<style></style>内に + の2行分を追加する。
76行目から

.blog-posts-link ul li a:hover {
  background-color: #ddd;
}
これを
.blog-posts-link ul li a:hover {
  background-color: #ddd;
	position: relative;
	width: fit-content;
}
こう

サイドバーを画面に追従させる

参考

サイドバーにあまり中身がない場合、サイドバーは常に画面内にあった方が楽だということに気づいたので実装します。ダークモードのトグルボタンがあるので、切り替えを簡単にしてモードごとの表示の違いを速やかに確認できるようにしたいです。(自分用)

src\layouts\Layout.astroの177行目付近

aside {
    order: 1;
    width: 300px;
    padding: 20px 20px;
    background-color: #f4f4f4;
  }
これを
aside {
    order: 1;
    width: 300px;
    padding: 20px 20px;
    background-color: #f4f4f4;
		position: sticky;
    top: 0;
    height: 100vh;
  }
こうする

これによって、記事をスクロールしても常にサイドバーが表示されるようになりました。

問題

しかし、サイドバーの中身がサイドバーより大きくなる時のことを想定していませんでした。

Image in a image block

サイドバーが横にあるとき、サイドバーの下の方にあるタグが見えなくなってしまいました。

Image in a image block

これは画面の横幅が減って、サイドバーが下に移ったときの様子です。

サイドバーの背景は濃い灰色の方です。ウィンドウの高さを小さくすると、サイドバーの中身がサイドバーからはみ出しています。

原因

まず、サイドバーの高さはheight: 100vh;と指定されているので、常に画面の高さに一致します。これにより、サイドバーが横にあるときに画面内に固定され、追従するようになります。

ウィンドウサイズを変更すると、それに合わせてサイドバーの高さが変わります。しかし、サイドバーが下にある時に、画面の高さを小さくしすぎてサイドバー内のコンテンツより小さくなると、下のGIFのようにサイドバー内コンテンツがはみ出してきて、その後ろには背景が見えるようになります。

Image in a image block

改善点

2点あります。

  • 横にあるサイドバーの中身が多すぎるとき、サイドバー内でスクロールできるようにして、下の方にあるサイドバー内コンテンツが見えるようにする。
  • 下にあるサイドバーの中身より画面が小さくなっても、サイドバーの中身が溢れないようにする。

サイドバーにスクロールを実装する

overflow-y: scroll;overflow-y: auto;を使います。y方向(上下方向)に中身が溢れたときにどうするか選ぶプロパティです。overflow-y: scroll;だと中身が溢れてなくても常時スクロールバーが付くらしいので、overflow-y: auto;にして溢れたらスクロールバーを付けるようにします。

Image in a image block

すると、見慣れたデザインのスクロールバーがサイドバー内に出現しました。しかし、タイトル部分にマウスカーソルが乗ると、横スクロールも出現しています。overflow-xは使っていないのですが、謎です。

サイドバー内に横スクロールは不要なので、明示的にオフにするためにoverflow-x: hidden;を追加しました。

これでもう出ません。

Image in a image block

iPadでどうなっているか確認します。ちゃんと動いていますね。

Image in a image block
iPad miniの横画面モード

これで完成にしようと思いましたが、PC画面で見えているスクロールバーの見た目が気になったのでどうするか考えます。

まず、ホバー時のみスクロールを有効にできるようにしました。すると、マウスカーソルがサイドバーに無いときはスクロールバーが消えます。

aside:hover {
    overflow-x: hidden;
    overflow-y: auto;
  }

こうすると今度は、マウスカーソルが無いiPadではホバーという条件が満たせないため、iPadでのサイドバーからスクロール機能がなくなりました。

iPadで動作しつつ、ホバー時にのみスクロールバーが表示されるようにする方法を考えます。

条件

  1. iPadのために常時overflow-x: hidden;overflow-y: auto;
  2. ホバー時以外(通常時)ではスクロールバー非表示
  3. ホバー時は、カスタマイズした見た目のスクロールバー表示

結果がこれです。

aside {
    order: 1;
    width: 300px;
    padding: 20px 20px;
    background-color: #f4f4f4;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
    &::-webkit-scrollbar {
      display: none;
    }
    &:hover {
      &::-webkit-scrollbar {
        display: block;
        width: 5px;
      }
      &::-webkit-scrollbar-thumb {
        background: #0000004d;
      }
      &::-webkit-scrollbar-track {
        background: #0000001a;
      }
    }
  }

普段はスクロールバーをdisplay: none;にして、ホバー時のみdisplay: block;で上書きして表示します。その下は見た目の設定です。

これで、Chrome・Edge・iPadのSafariはOKです。PCの方のSafariは分かりません。

Firefoxは-webkit-に対応していないらしいので別で設定要るかと思ったんですが、インストールして見てみると、デフォルトで隠れていてホバー時に表示し、しかもシンプルな見た目なので別に要らないですね。後からCSSの仕様が変わっても困るので放置することにしました。

Image in a image block

この時点でお気づきの方もいらっしゃるかと思いますが、サイドバーの記事名のホバーが消えてしまっています。

src\components\BlogPostsLink.astroから、記事名はホバー表示ではなく、折返しによって全て表示するように切り替えます。

記事名を折り返し表示させる

.blog-posts-link ul li a {
    display: block;
    border-radius: var(--radius);
    padding: 0.4rem 0.4rem;
    line-height: 1.2rem;
    color: inherit;
    font-size: 0.95rem;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
.blog-posts-link ul li a {
    display: block;
    border-radius: var(--radius);
    padding: 0.4rem 0.4rem;
    line-height: 1.2rem;
    color: inherit;
    font-size: 0.95rem;
  }

overflow: hidden; white-space: nowrap; text-overflow: ellipsis;を削除することで、記事名を折り返すようにします。ついでにホバー表示用に追加した部分は削除しておきます。

.blog-posts-link ul li a:hover {
  background-color: #ddd;
	position: relative;
	width: fit-content;
}
.blog-posts-link ul li a:hover {
  background-color: #ddd;
}

これで折り返し表示されるようになりました。しかし、今度は別のことが気になります。スクロールバーが表示されると、その幅の分だけ押し込まれて記事の折返し位置がズレます。気になって仕方がありません。

Image in a image block

これは、display: none;によってスクロールバーが消えていることが原因です。

サイドバーに透明化するスクロールを実装する

スクロールバーを常時存在させて、色だけ完全に透明にすることでdisplay: none;の代わりにします。透明になって見えないだけで、サイドバーはそこに「在る」ので記事の折返しがずれることはなくなります。

ホバー時にのみ、スクロールバーの各要素に色が付くようにしました。

aside {
    order: 1;
    width: 300px;
    padding: 20px 20px;
    background-color: #f4f4f4;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
    &::-webkit-scrollbar {
      width: 5px;
    }
    &::-webkit-scrollbar-thumb {
      background: #00000000;
    }
    &::-webkit-scrollbar-track {
      background: #00000000;
    }
    &:hover {
      &::-webkit-scrollbar-thumb {
        background: #0000004d;
      }
      &::-webkit-scrollbar-track {
        background: #0000001a;
      }
    }
  }

これでサイドバーが横にあるときの問題を解決しました。

下にあるサイドバーの中身が飛び出さないようにする

今度は簡単です。サイドバーの中身が飛び出してしまうのは、サイドバーの高さをheight: 100vh;によって定めていたからでした。これを、サイドバーの中身の高さにします。height: 100%;です。

メディアクエリのブレイクポイントでサイドバーが下になったときの設定部分を変更します。これで、サイドバーが下のときは、height: 100%;で上書きされるようになりました。

@media (max-width: 640px) {
    aside {
      order: 2;
      width: 100%;
    }
  }
@media (max-width: 640px) {
    aside {
      order: 2;
      width: 100%;
      height: 100%;
    }
  }

これで問題なく動作しているんですが、サイドバーが下になったときにサイドバー内のスクロール機能は必要ありません。

height: 100%;によってoverflow自体が起こらなくなるので要らないとは思うんですが、気持ち悪いので明示的に書いておきます。overflow-x: hidden;は外にあるのでoverflow-y: hidden;だけ。

@media (max-width: 640px) {
    aside {
      order: 2;
      width: 100%;
      height: 100%;
      overflow-y: hidden;
    }
  }

これでOKです。

あとがき

何かいじったら気になる点が出てくる連鎖がなかなか止まらなくて大変でした。

サイドバーは使いやすさに直結する部分なので、こだわればこだわっただけ操作感に反映されるのが楽しいです。