Gatsbyのカスタマイズ - ナビゲーションメニューとカラムレイアウト

時代はモバイルファーストかもしれないけど、(自分も含めて)対象読者として想定しているエンジニアの大半は、PC で表示する機会が多いと思う。ところがモバイルファーストに割り切っている Gatsby Starter Blog を横長の画面で表示すると、両端の大きなデッドスペース が目立つ。どうしても勿体なく感じてしまう。そしてナビゲーション機能が乏しい点もどうにかしたい。

Gatsby Starter Blog

そこで、ヘッダにナビゲーションメニューを設置し、ページのメイン領域を 2 カラムレイアウトにして、横の余白に記事の目次やら何かしらのウィジェットを配置するようにしたい。PC ファースト(笑)とは言え、もちろんレスポンシブ対応はする。

前提条件

既に React-Bootstrap が適用済みである事を前提とする。適用方法は こちらの記事 で説明している。Gatsby Starter Blog を利用しているが、他のスタータでも大きな違いはないはず。

ナビゲーションメニュー

幅が狭い画面ではハンバーガーメニューが表示されるようにする。ウィンドウの上方にスティッキーにするのは迷ったけど、画面が狭くなるから今回は止めた。

Navigation Bar in Wide Screen

Navigation Bar in Narrow Screen

実装

ナビゲーションメニューは React-Bootstrap の NavBar コンポーネントと、Nav コンポーネントを組み合わせて実装する。

<Navbar bg="light" expand="lg" className="mb-5">
  <Container>
    <Link to="/" className="navbar-brand">
      <StaticImage
        src="../images/favicon_io/favicon-32x32.png"
        width={32}
        height={32}
        formats={["auto", "webp", "avif"]}
        className="d-inline-block align-top me-2"
        quality={95}
        alt=""
      />
      {siteTitle}
    </Link>
    <Navbar.Toggle aria-controls="responsive-navbar-nav" />
    <Navbar.Collapse id="responsive-navbar-nav">
      <Nav className="ms-auto">
        <Nav.Item>
          <Link to="/tags/react/" className="nav-link">
            React
          </Link>
        </Nav.Item>
      </Nav>
    </Navbar.Collapse>
  </Container>
</Navbar>

Gatsby の StaticImage コンポーネントを利用して、ロゴを挿入している。また、Navbar.Toggle コンポーネントと Navbar.Collapse コンポーネントによって、レスポンシブ対応している。

ポイント

ここでいちばん大切なのは、リンクの貼り方だ。React-Bootstrap の Navbar.Brand コンポーネントと Nav.Link コンポーネントを利用せず、代わりに 内部リンクに最適化 された Gatsby Link コンポーネントを利用するようにする。<Link to="/about/" className="nav-link">... のように、Bootstrap のクラスを指定しすれば良い。

カラムレイアウト

幅によってレスポンシブに、2 カラムになったり 1 カラムになったりする、お馴染みのレイアウトを構成する。右側のサイドバーにはプロフィールとタグ一覧のウィジェットを表示する。

2-Column Layout in Wide Screen

横方向の広さが命の数式にも、出来る限り支障をきたさないように、ある程度の横幅が確保できるまで 1 カラムを維持する。

2-Column Layout in Narrow Screen

実装

React-Bootstrap のグリッドシステム を利用して、Layout コンポーネント (src/components/Layout.js) を実装する。レスポンシブに変化する境界を lg として、出来る限りメイン領域の幅を広めに確保するようにしている。

<Container>
  <Row>
    <Col lg={8}>
      <main>{children}</main>
    </Col>
    <Col lg={4}>
      <Bio />
      <Tags />
    </Col>
  </Row>
  <footer className="py-4">
    © {new Date().getFullYear()}, Built with
    {` `}
    <a href="https://www.gatsbyjs.com">Gatsby</a>
  </footer>
</Container>

タグ一覧ウィジェット

サイドバーに表示するタグ一覧ウィジェット Tags コンポーネント(src/components/Tags.js)を作成する。Gatsby のカスタマイズ - マークダウン記事のタグ機能 のタグの一覧表示と同じ要領で簡単にできる。

const Tags = () => {
  const data = useStaticQuery(graphql`
    query {
      allMarkdownRemark(limit: 2000) {
        group(field: frontmatter___tags) {
          fieldValue
          totalCount
        }
      }
    }
  `);

  return (
    <div className="mb-4 p-3 bg-light">
      <h2>Tags</h2>
      <ul className="m-0 list-unstyled">
        {data.allMarkdownRemark.group.map((tag) => (
          <li key={tag.fieldValue}>
            <Link to={`/tags/${kebabCase(tag.fieldValue)}/`}>
              {tag.fieldValue} ({tag.totalCount})
            </Link>
          </li>
        ))}
      </ul>
    </div>
  );
};

参考リンク

Gatsby に React bootstrap 導入とナビゲーションバー - Qiita